Browse Source

add group join agree & encrypted-key added request

pull/18/head
Sun 4 years ago
parent
commit
4d6daf2467
  1. 4
      lib/apps/group_chat/provider.dart
  2. 31
      src/apps/group_chat/layer.rs
  3. 116
      src/apps/group_chat/models.rs
  4. 16
      src/apps/group_chat/rpc.rs
  5. 3
      src/migrate/group_chat.rs

4
lib/apps/group_chat/provider.dart

@ -94,8 +94,8 @@ class GroupChatProvider extends ChangeNotifier {
// //
} }
join(String gid, String gaddr, String name, String remark) { join(String gid, String gaddr, String name, String remark, [String key = '']) {
rpc.send('group-chat-join', [gid, gaddr, name, remark]); rpc.send('group-chat-join', [gid, gaddr, name, remark, key]);
} }
messageCreate(MessageType mtype, String content) { messageCreate(MessageType mtype, String content) {

31
src/apps/group_chat/layer.rs

@ -15,7 +15,7 @@ use tdn_did::Proof;
use crate::layer::{Layer, Online}; use crate::layer::{Layer, Online};
use crate::storage::{group_chat_db, write_avatar_sync}; use crate::storage::{group_chat_db, write_avatar_sync};
use super::models::{from_network_message, GroupChat, Member}; use super::models::{from_network_message, GroupChat, Member, Request};
use super::{add_layer, rpc}; use super::{add_layer, rpc};
pub(crate) async fn handle( pub(crate) async fn handle(
@ -73,9 +73,11 @@ pub(crate) async fn handle(
// 3. online to UI. // 3. online to UI.
results.rpcs.push(rpc::group_online(mgid, group.id)); results.rpcs.push(rpc::group_online(mgid, group.id));
// 5. sync group height. // 4. TODO online ping.
// 5. TODO sync group height.
if group.height < height { if group.height < height {
// TOOD //
} }
} else { } else {
let msg = SendType::Result(0, addr, false, false, vec![]); let msg = SendType::Result(0, addr, false, false, vec![]);
@ -87,11 +89,26 @@ pub(crate) async fn handle(
GroupResult::Waiting(_gcd) => { GroupResult::Waiting(_gcd) => {
// TODO waiting // TODO waiting
} }
GroupResult::Agree(_gcd, _group_info, _height) => { GroupResult::Agree(gcd, info, height) => {
// TOOD let base = layer.read().await.base.clone();
let db = group_chat_db(&base, &mgid)?;
let (rid, key) = Request::over(&db, &gcd, true)?;
// 1. add group chat.
let mut group = GroupChat::from_info(key, info, height, addr, base, &mgid)?;
group.insert(&db)?;
// 2. update UI.
results.rpcs.push(rpc::group_agree(mgid, rid, group));
// 3. online ping.
// 4. sync group height.
} }
GroupResult::Reject(_gcd) => { GroupResult::Reject(gcd) => {
// TOOD let db = group_chat_db(layer.read().await.base(), &mgid)?;
let (rid, _key) = Request::over(&db, &gcd, true)?;
results.rpcs.push(rpc::group_reject(mgid, rid));
} }
} }
} }

116
src/apps/group_chat/models.rs

@ -15,7 +15,7 @@ use crate::storage::{
group_chat_db, write_avatar_sync, write_file_sync, write_image_sync, write_record_sync, group_chat_db, write_avatar_sync, write_file_sync, write_image_sync, write_record_sync,
}; };
pub(super) struct GroupChatKey(Vec<u8>); pub(crate) struct GroupChatKey(Vec<u8>);
impl GroupChatKey { impl GroupChatKey {
pub fn new(value: Vec<u8>) -> Self { pub fn new(value: Vec<u8>) -> Self {
@ -137,6 +137,77 @@ impl GroupChat {
} }
} }
fn new_from(
g_id: GroupId,
height: i64,
owner: GroupId,
g_type: GroupType,
g_addr: PeerAddr,
g_name: String,
g_bio: String,
is_need_agree: bool,
key: GroupChatKey,
) -> Self {
let start = SystemTime::now();
let datetime = start
.duration_since(UNIX_EPOCH)
.map(|s| s.as_secs())
.unwrap_or(0) as i64; // safe for all life.
Self {
owner,
g_id,
g_type,
g_addr,
g_name,
g_bio,
is_need_agree,
key,
datetime,
id: 0,
height,
is_top: true,
is_ok: true,
is_closed: false,
last_datetime: datetime,
last_content: Default::default(),
last_readed: true,
online: false,
is_deleted: false,
}
}
pub fn from_info(
key: GroupChatKey,
info: GroupInfo,
height: i64,
addr: PeerAddr,
base: PathBuf,
mgid: &GroupId,
) -> Result<Self> {
match info {
GroupInfo::Common(owner, _, g_id, g_type, agree, name, g_bio, avatar) => {
write_avatar_sync(&base, &mgid, &g_id, avatar)?;
Ok(Self::new_from(
g_id, height, owner, g_type, addr, name, g_bio, agree, key,
))
}
GroupInfo::Encrypted(owner, _, g_id, agree, _hash, _name, _bio, avatar) => {
// TODO decrypted.
let g_type = GroupType::Encrypted;
let name = "".to_owned();
let bio = "".to_owned();
write_avatar_sync(&base, &mgid, &g_id, avatar)?;
Ok(Self::new_from(
g_id, height, owner, g_type, addr, name, bio, agree, key,
))
}
}
}
pub fn to_group_info(self, name: String, avatar: Vec<u8>) -> GroupInfo { pub fn to_group_info(self, name: String, avatar: Vec<u8>) -> GroupInfo {
match self.g_type { match self.g_type {
GroupType::Common | GroupType::Open => GroupInfo::Common( GroupType::Common | GroupType::Open => GroupInfo::Common(
@ -304,6 +375,7 @@ pub(crate) struct Request {
pub gid: GroupId, pub gid: GroupId,
pub addr: PeerAddr, pub addr: PeerAddr,
pub name: String, pub name: String,
key: GroupChatKey,
remark: String, remark: String,
is_ok: bool, is_ok: bool,
is_over: bool, is_over: bool,
@ -326,13 +398,20 @@ impl Request {
name, name,
remark, remark,
datetime, datetime,
key: GroupChatKey(vec![]),
is_ok: false, is_ok: false,
is_over: false, is_over: false,
id: 0, id: 0,
} }
} }
pub fn new_by_me(gid: GroupId, addr: PeerAddr, name: String, remark: String) -> Self { pub fn new_by_me(
gid: GroupId,
addr: PeerAddr,
name: String,
remark: String,
key: GroupChatKey,
) -> Self {
let start = SystemTime::now(); let start = SystemTime::now();
let datetime = start let datetime = start
.duration_since(UNIX_EPOCH) .duration_since(UNIX_EPOCH)
@ -345,6 +424,7 @@ impl Request {
name, name,
remark, remark,
datetime, datetime,
key,
is_ok: false, is_ok: false,
is_over: false, is_over: false,
fid: 0, fid: 0,
@ -367,12 +447,13 @@ impl Request {
} }
pub fn insert(&mut self, db: &DStorage) -> Result<()> { pub fn insert(&mut self, db: &DStorage) -> Result<()> {
let sql = format!("INSERT INTO requests (fid, gid, addr, name, remark, is_ok, is_over, datetime, is_deleted) VALUES ({}, '{}', '{}', '{}', '{}', {}, {}, {}, false)", let sql = format!("INSERT INTO requests (fid, gid, addr, name, remark, key, is_ok, is_over, datetime, is_deleted) VALUES ({}, '{}', '{}', '{}', '{}', '{}', {}, {}, {}, false)",
self.fid, self.fid,
self.gid.to_hex(), self.gid.to_hex(),
self.addr.to_hex(), self.addr.to_hex(),
self.name, self.name,
self.remark, self.remark,
self.key.to_hex(),
if self.is_ok { 1 } else { 0 }, if self.is_ok { 1 } else { 0 },
if self.is_over { 1 } else { 0 }, if self.is_over { 1 } else { 0 },
self.datetime, self.datetime,
@ -382,6 +463,33 @@ impl Request {
self.id = id; self.id = id;
Ok(()) Ok(())
} }
pub fn over(db: &DStorage, gcd: &GroupId, is_ok: bool) -> Result<(i64, GroupChatKey)> {
let matrix = db.query(&format!(
"SELECT id, key from requests WHERE gid = '{}' AND is_over = 0 ORDER BY id",
gcd.to_hex()
))?;
let mut requests = vec![];
for mut values in matrix {
let id = values.pop().unwrap().as_i64();
let key = GroupChatKey::from_hex(values.pop().unwrap().as_string())
.unwrap_or(GroupChatKey::new(vec![]));
requests.push((id, key));
}
let sql = format!(
"UPDATE requests SET is_ok={}, is_over=1 WHERE gid = '{}' AND is_over = 0",
if is_ok { 1 } else { 0 },
gcd.to_hex(),
);
db.update(&sql)?;
if requests.len() > 0 {
Ok(requests.pop().unwrap()) // safe.
} else {
Err(new_io_error("no requests"))
}
}
} }
/// Group Member Model. /// Group Member Model.
@ -629,7 +737,7 @@ impl Message {
} }
pub(super) fn to_network_message( pub(super) fn to_network_message(
mtype: MessageType, _mtype: MessageType,
content: &str, content: &str,
) -> Result<(NetworkMessage, i64)> { ) -> Result<(NetworkMessage, i64)> {
let start = SystemTime::now(); let start = SystemTime::now();

16
src/apps/group_chat/rpc.rs

@ -14,7 +14,7 @@ use crate::rpc::RpcState;
use crate::storage::group_chat_db; use crate::storage::group_chat_db;
use super::add_layer; use super::add_layer;
use super::models::{to_network_message, GroupChat, Member, Message, Request}; use super::models::{to_network_message, GroupChat, GroupChatKey, Member, Message, Request};
#[inline] #[inline]
pub(crate) fn create_check(mgid: GroupId, ct: CheckType, supported: Vec<GroupType>) -> RpcParam { pub(crate) fn create_check(mgid: GroupId, ct: CheckType, supported: Vec<GroupType>) -> RpcParam {
@ -37,6 +37,16 @@ pub(crate) fn group_offline(mgid: GroupId, fid: i64, gid: &GroupId) -> RpcParam
rpc_response(0, "group-chat-offline", json!([fid, gid.to_hex()]), mgid) rpc_response(0, "group-chat-offline", json!([fid, gid.to_hex()]), mgid)
} }
#[inline]
pub(crate) fn group_agree(mgid: GroupId, rid: i64, group: GroupChat) -> RpcParam {
rpc_response(0, "group-chat-agree", json!([rid, group.to_rpc()]), mgid)
}
#[inline]
pub(crate) fn group_reject(mgid: GroupId, rid: i64) -> RpcParam {
rpc_response(0, "group-chat-reject", json!([rid]), mgid)
}
#[inline] #[inline]
pub(crate) fn member_join(mgid: GroupId, member: Member) -> RpcParam { pub(crate) fn member_join(mgid: GroupId, member: Member) -> RpcParam {
rpc_response(0, "group-chat-member-join", json!(member.to_rpc()), mgid) rpc_response(0, "group-chat-member-join", json!(member.to_rpc()), mgid)
@ -192,8 +202,10 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) {
let gaddr = PeerAddr::from_hex(params[1].as_str()?)?; let gaddr = PeerAddr::from_hex(params[1].as_str()?)?;
let gname = params[2].as_str()?.to_owned(); let gname = params[2].as_str()?.to_owned();
let gremark = params[3].as_str()?.to_owned(); let gremark = params[3].as_str()?.to_owned();
let gkey = params[4].as_str()?;
let key = GroupChatKey::from_hex(gkey).unwrap_or(GroupChatKey::new(vec![]));
let mut request = Request::new_by_me(gcd, gaddr, gname, gremark); let mut request = Request::new_by_me(gcd, gaddr, gname, gremark, key);
let db = group_chat_db(state.layer.read().await.base(), &gid)?; let db = group_chat_db(state.layer.read().await.base(), &gid)?;
request.insert(&db)?; request.insert(&db)?;
drop(db); drop(db);

3
src/migrate/group_chat.rs

@ -25,7 +25,8 @@ pub(super) const GROUP_CHAT_VERSIONS: [&str; 4] = [
gid TEXT NOT NULL, gid TEXT NOT NULL,
addr TEXT NOT NULL, addr TEXT NOT NULL,
name TEXT NOT NULL, name TEXT NOT NULL,
remark TEXT, remark TEXT NOT NULL,
key TEXT NOT NULL,
is_ok INTEGER NOT NULL, is_ok INTEGER NOT NULL,
is_over INTEGER NOT NULL, is_over INTEGER NOT NULL,
datetime INTEGER NOT NULL, datetime INTEGER NOT NULL,

Loading…
Cancel
Save