diff options
author | Quentin Dufour <quentin@deuxfleurs.fr> | 2024-05-29 10:14:51 +0200 |
---|---|---|
committer | Quentin Dufour <quentin@deuxfleurs.fr> | 2024-05-29 10:14:51 +0200 |
commit | b9ce5886033677f6c65a4b873e17574fdb8df31d (patch) | |
tree | 9ed1d721361027d7d6fef0ecad65d7e1b74a7ddb /aero-proto/src/imap/command/anonymous.rs | |
parent | 0dcf69f180f5a7b71b6ad2ac67e4cdd81e5154f1 (diff) | |
parent | 5954de6efbb040b8b47daf0c7663a60f3db1da6e (diff) | |
download | aerogramme-b9ce5886033677f6c65a4b873e17574fdb8df31d.tar.gz aerogramme-b9ce5886033677f6c65a4b873e17574fdb8df31d.zip |
Merge branch 'caldav'
Diffstat (limited to 'aero-proto/src/imap/command/anonymous.rs')
-rw-r--r-- | aero-proto/src/imap/command/anonymous.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/aero-proto/src/imap/command/anonymous.rs b/aero-proto/src/imap/command/anonymous.rs new file mode 100644 index 0000000..f23ec17 --- /dev/null +++ b/aero-proto/src/imap/command/anonymous.rs @@ -0,0 +1,84 @@ +use anyhow::Result; +use imap_codec::imap_types::command::{Command, CommandBody}; +use imap_codec::imap_types::core::AString; +use imap_codec::imap_types::response::Code; +use imap_codec::imap_types::secret::Secret; + +use aero_collections::user::User; +use aero_user::login::ArcLoginProvider; + +use crate::imap::capability::ServerCapability; +use crate::imap::command::anystate; +use crate::imap::flow; +use crate::imap::response::Response; + +//--- dispatching + +pub struct AnonymousContext<'a> { + pub req: &'a Command<'static>, + pub server_capabilities: &'a ServerCapability, + pub login_provider: &'a ArcLoginProvider, +} + +pub async fn dispatch(ctx: AnonymousContext<'_>) -> Result<(Response<'static>, flow::Transition)> { + match &ctx.req.body { + // Any State + CommandBody::Noop => anystate::noop_nothing(ctx.req.tag.clone()), + CommandBody::Capability => { + anystate::capability(ctx.req.tag.clone(), ctx.server_capabilities) + } + CommandBody::Logout => anystate::logout(), + + // Specific to anonymous context (3 commands) + CommandBody::Login { username, password } => ctx.login(username, password).await, + CommandBody::Authenticate { .. } => { + anystate::not_implemented(ctx.req.tag.clone(), "authenticate") + } + //StartTLS is not implemented for now, we will probably go full TLS. + + // Collect other commands + _ => anystate::wrong_state(ctx.req.tag.clone()), + } +} + +//--- Command controllers, private + +impl<'a> AnonymousContext<'a> { + async fn login( + self, + username: &AString<'a>, + password: &Secret<AString<'a>>, + ) -> Result<(Response<'static>, flow::Transition)> { + let (u, p) = ( + std::str::from_utf8(username.as_ref())?, + std::str::from_utf8(password.declassify().as_ref())?, + ); + tracing::info!(user = %u, "command.login"); + + let creds = match self.login_provider.login(&u, &p).await { + Err(e) => { + tracing::debug!(error=%e, "authentication failed"); + return Ok(( + Response::build() + .to_req(self.req) + .message("Authentication failed") + .no()?, + flow::Transition::None, + )); + } + Ok(c) => c, + }; + + let user = User::new(u.to_string(), creds).await?; + + tracing::info!(username=%u, "connected"); + Ok(( + Response::build() + .to_req(self.req) + .code(Code::Capability(self.server_capabilities.to_vec())) + .message("Completed") + .ok()?, + flow::Transition::Authenticate(user), + )) + } +} |