use crate::{AppState, log, LogLevel::*}; use super::{JsonBack, errcode0, token}; use super::{token_fail,check_token}; use crate::datasource::Datasource; use serde::{Serialize, Deserialize}; use axum::{Json,extract::{State}, http::HeaderMap}; #[derive(Deserialize)] pub struct TaskOfDeviceShareOrTransfer{ token: String, id: u64, r#type: u8, } #[derive(Serialize)] pub struct UrlBack{ errcode: u16, errmsg: Option, url: Option, } #[allow(unused_variables)] pub async fn new_flow_task_share_device( headers: HeaderMap, State(state): State, Json(u): axum::extract::Json ) -> Json { let (uid,_) = match check_token(&state, u.token).await { Ok(id) => {id}, Err(_) => { return Json(UrlBack{errcode: 3000, errmsg: Some(format!("鉴权失败: token失效")),url:None}); } }; match u.r#type{ 0|1|2 => {}, _ => { return Json(UrlBack{errcode: 3000, errmsg: Some(format!("参数错误: type应为0、1、2")),url:None}); } } let mut tryno=0; let linkrand = token(32); while tryno<5 && match state.db_lite.execute( "insert into flow_task_share (did, typo, ticket,createby)values (?,?,?,?)", (u.id,u.r#type,linkrand.clone(),uid)).await{ Ok(_) => false, Err(e) => if e==""{true} // execute时如果遇到Unique异常时会将异常处理为空字符串 else{return Json(UrlBack{errcode: 3000, errmsg: Some(format!("分享流程创建失败: {e}")),url:None})}, } { tryno+=1; }; if tryno==5{ return Json(UrlBack{errcode: 3000, errmsg: Some(format!("分享流程创建失败: 反复重试失败")),url: None}); } // 获取主机名 // let host = format!("https://{}",headers.get("host") // .and_then(|hv| hv.to_str().ok()) // .unwrap_or("localhost:3000")); let host = crate::WEBP; Json(UrlBack{errcode: 0, errmsg: None,url:Some(format!("{host}?linkrand={linkrand}"))}) } // #[derive(Deserialize)] // pub struct QueryParams { // linkrand: String, // } #[derive(Deserialize)] pub struct CheckoutShare { token: String, linkrand: String, } pub async fn checkout_flow_task_of_share_device( State(state): State, // Query(params): Query, Json(u): Json ) -> Json { let (uid, mqid) = match check_token(&state, u.token).await { Ok(uid) => uid, Err(_) => { return token_fail(); } }; let (the_id,sn, typo,interval, createby) = match state.db_lite.query( "select f.did,d.sn,f.typo,strftime('%s','now')-strftime('%s',createtime),f.createby from flow_task_share f left join device d on f.did=d.id where f.ticket=? and f.isdelete=0", [ // params.linkrand.clone() u.linkrand.clone() ], |r|Ok((r.get::(0)?,r.get::(1)?,r.get::(2)?,r.get::(3)?,r.get::(4)?))).await{ Ok(a) => a, Err(_) => return Json(JsonBack{errcode: 3000, errmsg: Some( "未找到分享流程".to_string() // format!("未找到分享流程 {} {e}",params.ticket.clone()) )}), }; if interval > 30*60 /* interval为当前时间减去createtime的秒数 */ { match state.db_lite.execute( "delete from flow_task_share where ticket=?", // "update flow_task_share set isdelete=1 where ticket=?", [u.linkrand.clone()]).await{ Ok(_) => {}, Err(e) => return Json(JsonBack{errcode: 3000, errmsg: Some(format!("删除分享流程失败: {e}"))}), }; return Json(JsonBack{errcode: 3000, errmsg: Some("分享流程已过期".to_string())}); } // 为2时转让设备,需要移除原用户与设备的关系 if typo == 2{ if let Err(e) = state.db_lite.execute("delete from map_user_device where uid=? and did=?", (createby, the_id)).await{ return Json(JsonBack{errcode: 3000, errmsg: Some(format!("转让时删除设备关系失败: {e}"))}); } } // 为0时分享区域 if typo == 0{ match state.db_lite.execute("insert into map_user_area(uid,aid)values(?,?)", [uid, the_id]).await{ Ok(i) => { log(Debug, format!("影响一级区域数量{i}个")); }, Err(e) => if e==""{/*Unique异常跳过 */} else {return Json(JsonBack{errcode: 3000, errmsg: Some(format!("添加区域分享关系失败: {e}"))});}, }; match state.db_lite.execute("insert into map_user_area(uid,aid) select ?,id from area where sup=? and id not in (select aid from map_user_area where uid=?)", [uid, the_id,uid]).await{ Ok(i) => { log(Debug, format!("影响二级区域数量{i}个")); }, Err(e) => if e==""{/*Unique异常跳过 */} else {return Json(JsonBack{errcode: 3000, errmsg: Some(format!("添加区域下级分享关系失败: {e}"))})}, }; match state.db_lite.execute("insert into map_user_device(uid,did) select ?,device.id from device where area in (select id from area where area.sup=?) and device.id not in (select did from map_user_device where uid=?)", [uid, the_id,uid]).await{ Ok(i) => { log(Debug, format!("影响设备数量{i}个")); }, Err(e) =>if e==""{/*Unique异常跳过 */} else { return Json(JsonBack{errcode: 3000, errmsg: Some(format!("添加区域下全部设备关系失败: {e}"))})}, }; } // 为1时分享设备,为2时转让设备,此处添加设备与新用户的关系 else if typo == 1 || typo == 2 { match state.db_lite.execute("insert into map_user_device(uid,did)values(?,?)", [uid, the_id]).await{ Ok(_) => {/*正常插入,可以跳过*/}, Err(e) => if e==""{/*Unique异常跳过*/}else{ return Json(JsonBack{errcode: 3000, errmsg: Some(format!("添加设备分享关系失败: {e}"))});} }; match state.db_lite.execute("delete from flow_task_share where ticket=?", [u.linkrand.clone()]).await{ Ok(_) => {}, Err(e) => {println!("when delete transform flow got error: {e}")} } // 添加监听 if let Some(ref s)=state.mq_detail{ // 插入新关系 if let Err(e)=s.db_mq_map.execute("insert into pub (clientid,topic)values(?,?),(?,?)", (mqid.clone(),format!("{sn}/cmd",),mqid.clone(),format!("/wf/Iot/device/{sn}",))).await{ log(Error, format!("添加设备失败: {e}")); } if let Err(e)=s.db_mq_map.execute("insert into sub (clientid,topic)values(?,?),(?,?)", (mqid.clone(),format!("{sn}/state",),mqid,format!("/wf/Iot/client/{sn}",))).await{ log(Error, format!("添加设备失败: {e}")); } } } else { return Json(JsonBack{errcode: 3000, errmsg: Some("分享流程类型错误".to_string())}); } // 转让设备需要将belongto更新 if typo == 2{ let (mqold, effected) = if let Ok(ans) = state.db_lite.query( "select d.mqid, count(*) from (select u.mqid mqid, d.id id from device d left join user u on u.id=d.belongto where d.id=?)d left join map_user_device m on d.id=m.did", [the_id], |r|Ok((r.get::(0)?,r.get::(1)?,))).await{ ans }else{ (String::new(),0) }; if effected!=1{ return Json(JsonBack { errcode: 3000, errmsg: Some(format!("该设备被分享状态占用,目前有{effected}条分享")) }); } match state.db_lite.execute("update device set belongto=? where id=?", [uid, the_id]).await{ Ok(_) => {}, Err(e) => return Json(JsonBack{errcode: 3000, errmsg: Some(format!("更新设备分享关系失败: {e}"))}), } if let Some(s)=state.mq_detail{ // 移除旧关系 if let Err(e)=s.db_mq_map.execute("delete from pub where clientid=? and topic in (?,?)", (mqold.clone(),format!("{sn}/cmd",),format!("/wf/Iot/device/{sn}",))).await{ log(Error, format!("删除设备失败: {e}")); } if let Err(e)=s.db_mq_map.execute("delete from sub where clientid=? and topic in (?,?)", (mqold,format!("{sn}/state",),format!("/wf/Iot/client/{sn}",))).await{ log(Error, format!("删除设备失败: {e}")); } } } else { match state.db_lite.execute("delete from flow_task_share where strftime('%s','now')-strftime('%s',createtime)>30*60", []).await{ Ok(_) => {}, Err(e) => {println!("when delete extra flow got error: {e}")} } } errcode0() }