fix(ws-org): enforce current_org_id for teacher-student APIs
Require organization context in teacher/student relation reads and writes, and prevent fallback to cross-organization queries. Made-with: Cursor
This commit is contained in:
+67
-133
@@ -16,6 +16,10 @@ fn current_org_id_from_token_str(token_str: &String) -> Option<String> {
|
||||
.and_then(|decoded| decoded.current_org_id)
|
||||
}
|
||||
|
||||
fn required_current_org_id_from_token_str(token_str: &String) -> anyhow::Result<String> {
|
||||
current_org_id_from_token_str(token_str).ok_or_else(|| anyhow!("current_org_id is required"))
|
||||
}
|
||||
|
||||
use htycommons::common::{
|
||||
current_local_datetime, get_page_and_page_size, get_some_from_query_params, strip_result_vec,
|
||||
HtyErr, HtyErrCode, HtyResponse,
|
||||
@@ -3142,6 +3146,7 @@ pub async fn raw_get_unclaimed_students(
|
||||
host: HtyHostHeader,
|
||||
db_pool: Arc<DbState>,
|
||||
) -> anyhow::Result<Vec<ReqHtyUserWithInfos>> {
|
||||
let current_org_id = required_current_org_id_from_token_str(&root.0)?;
|
||||
let url = format!("{}/find_users_with_info_by_role/STUDENT", get_uc_url(),);
|
||||
let client = reqwest::Client::new();
|
||||
let ret_json = client
|
||||
@@ -3161,11 +3166,12 @@ pub async fn raw_get_unclaimed_students(
|
||||
})?;
|
||||
let mut resp = vec![];
|
||||
for user_with_info in user_with_infos {
|
||||
let exist = TeacherStudent::verify_exist_and_not_deleted_by_student_id(
|
||||
let exist = TeacherStudent::verify_exist_and_not_deleted_by_student_id_in_org(
|
||||
user_with_info
|
||||
.hty_id
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("hty_id is required"))?,
|
||||
¤t_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
if !exist {
|
||||
@@ -3217,21 +3223,13 @@ pub async fn raw_claim_student(
|
||||
.clone()
|
||||
.ok_or_else(|| anyhow!("id_student is required"))?;
|
||||
|
||||
let current_org_id = current_org_id_from_token_str(&(*token).clone());
|
||||
let res_exist = if let Some(org_id) = ¤t_org_id {
|
||||
TeacherStudent::verify_exist_by_teacher_id_and_student_id_in_org(
|
||||
&id_teacher,
|
||||
&id_student,
|
||||
org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
} else {
|
||||
TeacherStudent::verify_exist_by_teacher_id_and_student_id(
|
||||
&id_teacher,
|
||||
&id_student,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
};
|
||||
let current_org_id = required_current_org_id_from_token_str(&(*token).clone())?;
|
||||
let res_exist = TeacherStudent::verify_exist_by_teacher_id_and_student_id_in_org(
|
||||
&id_teacher,
|
||||
&id_student,
|
||||
¤t_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
if res_exist {
|
||||
return Err(anyhow!(HtyErr {
|
||||
code: HtyErrCode::WebErr,
|
||||
@@ -3244,7 +3242,7 @@ pub async fn raw_claim_student(
|
||||
id: uuid(),
|
||||
status: String::from("Approved"),
|
||||
created_at: Some(current_local_datetime()),
|
||||
org_id: current_org_id,
|
||||
org_id: Some(current_org_id),
|
||||
};
|
||||
let res = TeacherStudent::create(
|
||||
&in_record,
|
||||
@@ -3340,42 +3338,25 @@ pub async fn raw_disclaim_student(
|
||||
.clone()
|
||||
.ok_or_else(|| anyhow!("id_student is required"))?;
|
||||
|
||||
let current_org_id = current_org_id_from_token_str(&(*auth).clone());
|
||||
let res_exist = if let Some(org_id) = ¤t_org_id {
|
||||
TeacherStudent::verify_exist_by_teacher_id_and_student_id_in_org(
|
||||
&id_teacher,
|
||||
&id_student,
|
||||
org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
} else {
|
||||
TeacherStudent::verify_exist_by_teacher_id_and_student_id(
|
||||
&id_teacher,
|
||||
&id_student,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
};
|
||||
let current_org_id = required_current_org_id_from_token_str(&(*auth).clone())?;
|
||||
let res_exist = TeacherStudent::verify_exist_by_teacher_id_and_student_id_in_org(
|
||||
&id_teacher,
|
||||
&id_student,
|
||||
¤t_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
if !res_exist {
|
||||
return Err(anyhow!(HtyErr {
|
||||
code: HtyErrCode::WebErr,
|
||||
reason: Some("no existing record for this teacher and student".into()),
|
||||
}));
|
||||
}
|
||||
let res = if let Some(org_id) = ¤t_org_id {
|
||||
TeacherStudent::del_by_teacher_id_and_student_id_in_org(
|
||||
&id_teacher,
|
||||
&id_student,
|
||||
org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
} else {
|
||||
let record = TeacherStudent::find_by_teacher_id_and_student_id(
|
||||
&id_teacher,
|
||||
&id_student,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
TeacherStudent::delete_by_id(&record.id, extract_conn(fetch_db_conn(&db_pool)?).deref_mut())?
|
||||
};
|
||||
let res = TeacherStudent::del_by_teacher_id_and_student_id_in_org(
|
||||
&id_teacher,
|
||||
&id_student,
|
||||
¤t_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
@@ -3579,19 +3560,12 @@ pub async fn raw_find_all_teachers_by_student_id(
|
||||
student_id: String,
|
||||
db_pool: Arc<DbState>,
|
||||
) -> anyhow::Result<Vec<ReqHtyUserWithInfos>> {
|
||||
let current_org_id = current_org_id_from_token_str(&root.0);
|
||||
let teacher_ids = if let Some(org_id) = ¤t_org_id {
|
||||
TeacherStudent::get_all_teachers_by_student_id_in_org(
|
||||
&student_id,
|
||||
org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
} else {
|
||||
TeacherStudent::get_all_teachers_by_student_id(
|
||||
&student_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
};
|
||||
let current_org_id = required_current_org_id_from_token_str(&root.0)?;
|
||||
let teacher_ids = TeacherStudent::get_all_teachers_by_student_id_in_org(
|
||||
&student_id,
|
||||
¤t_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
debug!(
|
||||
"raw_find_all_teachers_by_student_id -> teacher_ids {:?}",
|
||||
&teacher_ids
|
||||
@@ -3652,21 +3626,13 @@ pub async fn raw_delete_teacher_student(
|
||||
let _teacher = find_hty_user_with_info_by_id(&teacher_id, &root).await?;
|
||||
let _student = find_hty_user_with_info_by_id(&student_id, &root).await?;
|
||||
|
||||
let current_org_id = current_org_id_from_token_str(&root.0);
|
||||
let is_exist = if let Some(org_id) = ¤t_org_id {
|
||||
TeacherStudent::verify_exist_by_teacher_id_and_student_id_in_org(
|
||||
&teacher_id,
|
||||
&student_id,
|
||||
org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
} else {
|
||||
TeacherStudent::verify_exist_by_teacher_id_and_student_id(
|
||||
&teacher_id,
|
||||
&student_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
};
|
||||
let current_org_id = required_current_org_id_from_token_str(&root.0)?;
|
||||
let is_exist = TeacherStudent::verify_exist_by_teacher_id_and_student_id_in_org(
|
||||
&teacher_id,
|
||||
&student_id,
|
||||
¤t_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
|
||||
if !is_exist {
|
||||
return Err(anyhow!(HtyErr {
|
||||
@@ -3682,20 +3648,12 @@ pub async fn raw_delete_teacher_student(
|
||||
// )?;
|
||||
|
||||
// record.status = status;
|
||||
if let Some(org_id) = ¤t_org_id {
|
||||
let _ = TeacherStudent::del_by_teacher_id_and_student_id_in_org(
|
||||
&teacher_id,
|
||||
&student_id,
|
||||
org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
} else {
|
||||
let _ = TeacherStudent::del_by_teacher_id_and_student_id(
|
||||
&teacher_id,
|
||||
&student_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
}
|
||||
let _ = TeacherStudent::del_by_teacher_id_and_student_id_in_org(
|
||||
&teacher_id,
|
||||
&student_id,
|
||||
¤t_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -3753,41 +3711,25 @@ pub async fn raw_update_teacher_student(
|
||||
let _teacher = find_hty_user_with_info_by_id(&teacher_id, &root).await?;
|
||||
let _student = find_hty_user_with_info_by_id(&student_id, &root).await?;
|
||||
|
||||
let current_org_id = current_org_id_from_token_str(&root.0);
|
||||
let is_exist = if let Some(org_id) = ¤t_org_id {
|
||||
TeacherStudent::verify_exist_by_teacher_id_and_student_id_in_org(
|
||||
&teacher_id,
|
||||
&student_id,
|
||||
org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
} else {
|
||||
TeacherStudent::verify_exist_by_teacher_id_and_student_id(
|
||||
&teacher_id,
|
||||
&student_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
};
|
||||
let current_org_id = required_current_org_id_from_token_str(&root.0)?;
|
||||
let is_exist = TeacherStudent::verify_exist_by_teacher_id_and_student_id_in_org(
|
||||
&teacher_id,
|
||||
&student_id,
|
||||
¤t_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
if !is_exist {
|
||||
return Err(anyhow!(HtyErr {
|
||||
code: HtyErrCode::NullErr,
|
||||
reason: Some("no record for this teacher and student".to_string()),
|
||||
}));
|
||||
}
|
||||
let mut record = if let Some(org_id) = ¤t_org_id {
|
||||
TeacherStudent::find_by_teacher_id_and_student_id_in_org(
|
||||
&teacher_id,
|
||||
&student_id,
|
||||
org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
} else {
|
||||
TeacherStudent::find_by_teacher_id_and_student_id(
|
||||
&teacher_id,
|
||||
&student_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
};
|
||||
let mut record = TeacherStudent::find_by_teacher_id_and_student_id_in_org(
|
||||
&teacher_id,
|
||||
&student_id,
|
||||
¤t_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
record.status = status;
|
||||
let _ = TeacherStudent::update(&record, extract_conn(fetch_db_conn(&db_pool)?).deref_mut())?;
|
||||
Ok(())
|
||||
@@ -3834,21 +3776,13 @@ pub async fn raw_find_all_students_by_teacher_id_and_status(
|
||||
let status = req_teacher_student
|
||||
.status
|
||||
.ok_or_else(|| anyhow!("status is required"))?;
|
||||
let current_org_id = current_org_id_from_token_str(&root.0);
|
||||
let student_ids = if let Some(org_id) = ¤t_org_id {
|
||||
TeacherStudent::get_all_students_by_teacher_id_and_status_in_org(
|
||||
&teacher_id,
|
||||
&status,
|
||||
org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
} else {
|
||||
TeacherStudent::get_all_students_by_teacher_id_and_status(
|
||||
&teacher_id,
|
||||
&status,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?
|
||||
};
|
||||
let current_org_id = required_current_org_id_from_token_str(&root.0)?;
|
||||
let student_ids = TeacherStudent::get_all_students_by_teacher_id_and_status_in_org(
|
||||
&teacher_id,
|
||||
&status,
|
||||
¤t_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
debug!(
|
||||
"raw_find_all_students_by_teacher_id_and_status -> student_ids {:?}",
|
||||
&student_ids
|
||||
|
||||
@@ -3087,6 +3087,26 @@ impl TeacherStudent {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn verify_exist_and_not_deleted_by_student_id_in_org(
|
||||
id_student: &String,
|
||||
id_org: &String,
|
||||
conn: &mut PgConnection,
|
||||
) -> anyhow::Result<bool> {
|
||||
use crate::schema::teacher_student::dsl::*;
|
||||
select(exists(
|
||||
teacher_student
|
||||
.filter(student_id.eq(id_student).and(status.ne("Removed")))
|
||||
.filter(org_id.eq(id_org)),
|
||||
))
|
||||
.get_result(conn)
|
||||
.map_err(|e| {
|
||||
anyhow!(HtyErr {
|
||||
code: HtyErrCode::DbErr,
|
||||
reason: Some(e.to_string()),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn delete_all(conn: &mut PgConnection) -> anyhow::Result<usize> {
|
||||
match diesel::delete(teacher_student::table).execute(conn) {
|
||||
Ok(num) => Ok(num),
|
||||
|
||||
Reference in New Issue
Block a user