feat: handle new logins for same user
This commit is contained in:
parent
6649efc232
commit
1c5a3870c2
|
@ -11,8 +11,7 @@ use crate::{AuthenticateRequest, AuthenticateResponse, ClientState, State, User,
|
||||||
|
|
||||||
pub async fn authenticate(state: Arc<RwLock<State>>, client_state: Arc<RwLock<ClientState>>, conn: &mut WsStream, number: u32, req: AuthenticateRequest) -> anyhow::Result<()> {
|
pub async fn authenticate(state: Arc<RwLock<State>>, client_state: Arc<RwLock<ClientState>>, conn: &mut WsStream, number: u32, req: AuthenticateRequest) -> anyhow::Result<()> {
|
||||||
if client_state.read().await.user.is_some() {
|
if client_state.read().await.user.is_some() {
|
||||||
util::send(conn, number, AuthenticateResponse::error("already logged in")).await?;
|
return util::send(conn, number, AuthenticateResponse::error("already logged in")).await;
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = prefixed_api_key::parse(&*req.key)
|
let key = prefixed_api_key::parse(&*req.key)
|
||||||
|
@ -29,10 +28,7 @@ pub async fn authenticate(state: Arc<RwLock<State>>, client_state: Arc<RwLock<Cl
|
||||||
.context("could not query database for user")?;
|
.context("could not query database for user")?;
|
||||||
let mut user = match user {
|
let mut user = match user {
|
||||||
Some(u) => u,
|
Some(u) => u,
|
||||||
None => {
|
None => return util::send(conn, number, AuthenticateResponse::error("invalid key")).await,
|
||||||
util::send(conn, number, AuthenticateResponse::error("invalid key")).await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if Utc::now().naive_utc().signed_duration_since(user.last_updated) >= Duration::hours(2) {
|
if Utc::now().naive_utc().signed_duration_since(user.last_updated) >= Duration::hours(2) {
|
||||||
|
@ -59,6 +55,13 @@ pub async fn authenticate(state: Arc<RwLock<State>>, client_state: Arc<RwLock<Cl
|
||||||
|
|
||||||
let world = World::from_str(&user.world).map_err(|_| anyhow::anyhow!("invalid world in db"))?;
|
let world = World::from_str(&user.world).map_err(|_| anyhow::anyhow!("invalid world in db"))?;
|
||||||
|
|
||||||
|
if let Some(old_client_state) = state.read().await.clients.get(&(user.lodestone_id as u64)) {
|
||||||
|
let mut lock = old_client_state.write().await;
|
||||||
|
// this prevents the old client thread from removing info from the global state
|
||||||
|
lock.user = None;
|
||||||
|
lock.shutdown_tx.send(()).await.ok();
|
||||||
|
}
|
||||||
|
|
||||||
trace!(" [authenticate] before user write");
|
trace!(" [authenticate] before user write");
|
||||||
let mut c_state = client_state.write().await;
|
let mut c_state = client_state.write().await;
|
||||||
c_state.user = Some(User {
|
c_state.user = Some(User {
|
||||||
|
@ -81,7 +84,5 @@ pub async fn authenticate(state: Arc<RwLock<State>>, client_state: Arc<RwLock<Cl
|
||||||
state.write().await.ids.insert((user.name, util::id_from_world(world)), user.lodestone_id as u64);
|
state.write().await.ids.insert((user.name, util::id_from_world(world)), user.lodestone_id as u64);
|
||||||
trace!(" [authenticate] after state writes");
|
trace!(" [authenticate] after state writes");
|
||||||
|
|
||||||
util::send(conn, number, AuthenticateResponse::success()).await?;
|
util::send(conn, number, AuthenticateResponse::success()).await
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,6 +256,7 @@ async fn main() -> Result<()> {
|
||||||
pub struct ClientState {
|
pub struct ClientState {
|
||||||
user: Option<User>,
|
user: Option<User>,
|
||||||
tx: Sender<ResponseContainer>,
|
tx: Sender<ResponseContainer>,
|
||||||
|
shutdown_tx: Sender<()>,
|
||||||
pk: Vec<u8>,
|
pk: Vec<u8>,
|
||||||
allow_invites: bool,
|
allow_invites: bool,
|
||||||
}
|
}
|
||||||
|
@ -340,10 +341,12 @@ impl ClientState {
|
||||||
|
|
||||||
async fn client_loop(state: Arc<RwLock<State>>, mut conn: WsStream) -> Result<()> {
|
async fn client_loop(state: Arc<RwLock<State>>, mut conn: WsStream) -> Result<()> {
|
||||||
let (tx, mut rx) = tokio::sync::mpsc::channel(10);
|
let (tx, mut rx) = tokio::sync::mpsc::channel(10);
|
||||||
|
let (shutdown_tx, mut shutdown_rx) = tokio::sync::mpsc::channel(1);
|
||||||
|
|
||||||
let client_state = Arc::new(RwLock::new(ClientState {
|
let client_state = Arc::new(RwLock::new(ClientState {
|
||||||
user: None,
|
user: None,
|
||||||
tx,
|
tx,
|
||||||
|
shutdown_tx,
|
||||||
pk: Default::default(),
|
pk: Default::default(),
|
||||||
allow_invites: false,
|
allow_invites: false,
|
||||||
}));
|
}));
|
||||||
|
@ -351,6 +354,10 @@ async fn client_loop(state: Arc<RwLock<State>>, mut conn: WsStream) -> Result<()
|
||||||
loop {
|
loop {
|
||||||
let res: Result<()> = try {
|
let res: Result<()> = try {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
|
_ = shutdown_rx.recv() => {
|
||||||
|
debug!("break due to new login");
|
||||||
|
break;
|
||||||
|
}
|
||||||
msg = rx.recv() => {
|
msg = rx.recv() => {
|
||||||
if let Some(msg) = msg {
|
if let Some(msg) = msg {
|
||||||
let encoded = rmp_serde::to_vec(&msg)?;
|
let encoded = rmp_serde::to_vec(&msg)?;
|
||||||
|
|
Loading…
Reference in New Issue