Phase 2: PostgreSQL, E2EE, channel CRUD, voice signaling, Slint migration
Server: - PostgreSQL backend (Pool enum over Sqlite/PgPool, all storage methods dual-dialect) - E2EE for DM (4 new protobuf packets, handlers, storage of ciphertext only) - ChannelEdit packet + server-authoritative channel create/delete - Gateway → voice-node membership signaling via broadcast channel Client: - E2EE crypto (X25519 from Ed25519, HKDF, ChaCha20-Poly1305) + UI lock icons - E2EE net layer (PID 0x0071-0x0074, JSON payloads, dispatch, session handlers) - Slint migration: all .slint files, bridge.rs, update.rs, main.rs rewritten - Removed egui UI (~50 files) and all dead code (clean clippy -D warnings)
This commit is contained in:
parent
c34ed2a192
commit
742cf03a5f
31 changed files with 2203 additions and 639 deletions
92
gateway/src/handler/channel/edit.rs
Normal file
92
gateway/src/handler/channel/edit.rs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
use anyhow::Result;
|
||||
use prost::Message;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tracing::{info, warn};
|
||||
|
||||
use crate::{
|
||||
domain::{channels, session},
|
||||
net::{
|
||||
io,
|
||||
state::{BroadcastMsg, State},
|
||||
},
|
||||
proto::{ChannelEditPayload, PacketId, SessionCrypto, encode_packet, to_payload},
|
||||
};
|
||||
|
||||
pub async fn handle_channel_edit(
|
||||
stream: &mut (impl AsyncRead + AsyncWrite + Unpin),
|
||||
seq: &mut u32,
|
||||
session_id: &str,
|
||||
payload: &[u8],
|
||||
crypto: &SessionCrypto,
|
||||
state: &State,
|
||||
) -> Result<()> {
|
||||
let req = ChannelEditPayload::decode(payload)?;
|
||||
let sess = match session::get(&state.sessions, session_id).await {
|
||||
Some(s) => s,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let channel_id = req.channel_id.trim().to_string();
|
||||
let channel_name = req.channel_name.trim().to_string();
|
||||
|
||||
if channel_id.is_empty() || channel_name.is_empty() {
|
||||
io::send_encrypted(
|
||||
stream,
|
||||
PacketId::Error,
|
||||
seq,
|
||||
&to_payload(&crate::proto::ErrorPayload {
|
||||
code: crate::proto::ErrorCode::InvalidPacket as u32,
|
||||
message: "channel_id and channel_name are required".into(),
|
||||
}),
|
||||
crypto,
|
||||
)
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let renamed = channels::rename(&state.channels, &channel_id, &channel_name).await;
|
||||
|
||||
if !renamed {
|
||||
io::send_encrypted(
|
||||
stream,
|
||||
PacketId::Error,
|
||||
seq,
|
||||
&to_payload(&crate::proto::ErrorPayload {
|
||||
code: crate::proto::ErrorCode::ChannelNotFound as u32,
|
||||
message: "channel not found".into(),
|
||||
}),
|
||||
crypto,
|
||||
)
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Err(e) = state
|
||||
.storage
|
||||
.update_channel(&channel_id, &channel_name)
|
||||
.await
|
||||
{
|
||||
warn!("failed to update channel in storage: {e}");
|
||||
}
|
||||
|
||||
info!(
|
||||
"channel_edit: '{}' renamed to '{}' by {}",
|
||||
channel_id, channel_name, sess.nickname
|
||||
);
|
||||
|
||||
let _ = state.broadcast.send(BroadcastMsg {
|
||||
channel_id: Some(channel_id.clone()),
|
||||
exclude_session: Some(session_id.into()),
|
||||
target_session_id: None,
|
||||
data: encode_packet(
|
||||
PacketId::ChannelEdit,
|
||||
0,
|
||||
&to_payload(&ChannelEditPayload {
|
||||
channel_id: channel_id.clone(),
|
||||
channel_name: channel_name.clone(),
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue