From 5270c7a7832ab86a4b3ab7316e59fe97928d2595 Mon Sep 17 00:00:00 2001 From: Aumetra Weisman Date: Sat, 6 Apr 2024 20:58:30 +0200 Subject: [PATCH] progress --- Cargo.lock | 3 + crates/kitsune-error/Cargo.toml | 2 + crates/kitsune-error/src/axum.rs | 9 ++ crates/kitsune-error/src/lib.rs | 2 +- crates/kitsune-service/Cargo.toml | 1 + kitsune/src/http/extractor/signed_activity.rs | 20 ++--- kitsune/src/http/handler/confirm_account.rs | 3 +- kitsune/src/http/handler/custom_emojis.rs | 3 +- kitsune/src/http/handler/media.rs | 3 +- kitsune/src/http/handler/nodeinfo/two_one.rs | 3 +- kitsune/src/http/handler/oauth/authorize.rs | 2 +- kitsune/src/http/handler/oauth/token.rs | 8 +- kitsune/src/http/handler/oidc/callback.rs | 8 +- kitsune/src/http/handler/posts/activity.rs | 3 +- kitsune/src/http/handler/posts/mod.rs | 3 +- kitsune/src/http/handler/users/followers.rs | 3 +- kitsune/src/http/handler/users/following.rs | 3 +- kitsune/src/http/handler/users/inbox.rs | 85 ++++--------------- kitsune/src/http/handler/users/mod.rs | 3 +- kitsune/src/http/handler/users/outbox.rs | 3 +- .../src/http/handler/well_known/webfinger.rs | 5 +- kitsune/src/http/pagination.rs | 3 +- kitsune/src/http/util.rs | 5 +- kitsune/src/lib.rs | 2 +- 24 files changed, 72 insertions(+), 113 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 022eb4d05..4e3850909 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3824,7 +3824,9 @@ version = "0.0.1-pre.6" dependencies = [ "axum-core 0.4.3", "eyre", + "garde", "http 1.1.0", + "simd-json", "tracing", ] @@ -4112,6 +4114,7 @@ dependencies = [ "rsa", "rusty-s3", "serde", + "simd-json", "smol_str", "speedy-uuid", "tempfile", diff --git a/crates/kitsune-error/Cargo.toml b/crates/kitsune-error/Cargo.toml index 5d63f59ba..0d6eb8047 100644 --- a/crates/kitsune-error/Cargo.toml +++ b/crates/kitsune-error/Cargo.toml @@ -8,7 +8,9 @@ license.workspace = true [dependencies] axum-core = "0.4.3" eyre = "0.6.12" +garde = { version = "0.18.0", default-features = false } http = "1.1.0" +simd-json = "0.13.9" tracing = "0.1.40" [lints] diff --git a/crates/kitsune-error/src/axum.rs b/crates/kitsune-error/src/axum.rs index 62043e135..5a21aee04 100644 --- a/crates/kitsune-error/src/axum.rs +++ b/crates/kitsune-error/src/axum.rs @@ -24,6 +24,15 @@ impl IntoResponse for Error { fn into_response(self) -> Response { debug!(error = ?self.inner); + if let Some(garde_report) = self.inner.downcast_ref::() { + let body = match simd_json::to_string(&garde_report) { + Ok(body) => body, + Err(error) => return Error::from(error).into_response(), + }; + + return to_response(StatusCode::BAD_REQUEST, Some(body)); + } + match self.ty { ErrorType::BadRequest(maybe_body) => to_response(StatusCode::BAD_REQUEST, maybe_body), ErrorType::Forbidden(maybe_body) => to_response(StatusCode::FORBIDDEN, maybe_body), diff --git a/crates/kitsune-error/src/lib.rs b/crates/kitsune-error/src/lib.rs index 14b1230dd..6ee567fe3 100644 --- a/crates/kitsune-error/src/lib.rs +++ b/crates/kitsune-error/src/lib.rs @@ -14,7 +14,7 @@ pub type Result = std::result::Result; #[macro_export] macro_rules! bail { ($(type = $type:expr,)? $msg:expr) => { - return Err($crate::kitsune_error!($(type = $type,)? $msg)); + return Err($crate::kitsune_error!($(type = $type,)? $msg).into()); }; } diff --git a/crates/kitsune-service/Cargo.toml b/crates/kitsune-service/Cargo.toml index 9543b8f1f..7e912ac29 100644 --- a/crates/kitsune-service/Cargo.toml +++ b/crates/kitsune-service/Cargo.toml @@ -55,6 +55,7 @@ redis = { version = "0.25.3", default-features = false, features = [ rsa = "0.9.6" rusty-s3 = { version = "0.5.0", default-features = false } serde = "1.0.197" +simd-json = "0.13.9" smol_str = "0.2.1" speedy-uuid = { path = "../../lib/speedy-uuid" } tokio = { version = "1.37.0", features = ["macros", "sync"] } diff --git a/kitsune/src/http/extractor/signed_activity.rs b/kitsune/src/http/extractor/signed_activity.rs index 849ecc3d0..15adff0e7 100644 --- a/kitsune/src/http/extractor/signed_activity.rs +++ b/kitsune/src/http/extractor/signed_activity.rs @@ -13,7 +13,7 @@ use http::StatusCode; use http_body_util::BodyExt; use kitsune_core::{error::HttpError, traits::fetcher::AccountFetchOptions}; use kitsune_db::{model::account::Account, schema::accounts, with_connection, PgPool}; -use kitsune_error::{Error, Result}; +use kitsune_error::{bail, Error, ErrorType, Result}; use kitsune_type::ap::Activity; use kitsune_wasm_mrf::Outcome; use scoped_futures::ScopedFutureExt; @@ -77,13 +77,8 @@ impl FromRequest for SignedActivity { }; let ap_id = activity.actor.as_str(); - let Some(remote_user) = state - .fetcher - .fetch_account(ap_id.into()) - .await - .map_err(Error::Fetcher)? - else { - return Err(Error::CoreHttp(HttpError::BadRequest).into()); + let Some(remote_user) = state.fetcher.fetch_account(ap_id.into()).await? else { + bail!(type = ErrorType::BadRequest(None), "failed to fetch remote account"); }; let request = http::Request::from_parts(parts, ()); @@ -94,13 +89,8 @@ impl FromRequest for SignedActivity { .url(ap_id) .build(); - let Some(remote_user) = state - .fetcher - .fetch_account(opts) - .await - .map_err(Error::Fetcher)? - else { - return Err(Error::CoreHttp(HttpError::BadRequest).into()); + let Some(remote_user) = state.fetcher.fetch_account(opts).await? else { + bail!(type = ErrorType::BadRequest(None), "failed to fetch remote account"); }; if !verify_signature(&request, &state.db_pool, Some(&remote_user)).await? { diff --git a/kitsune/src/http/handler/confirm_account.rs b/kitsune/src/http/handler/confirm_account.rs index 56f3ca33a..67b060baa 100644 --- a/kitsune/src/http/handler/confirm_account.rs +++ b/kitsune/src/http/handler/confirm_account.rs @@ -1,10 +1,11 @@ -use crate::{error::Result, state::Zustand}; +use crate::state::Zustand; use axum::{ debug_handler, extract::{Path, State}, routing, Router, }; use kitsune_email::MailingService; +use kitsune_error::Result; use serde::Deserialize; #[derive(Deserialize)] diff --git a/kitsune/src/http/handler/custom_emojis.rs b/kitsune/src/http/handler/custom_emojis.rs index d96da6c5a..e5931c527 100644 --- a/kitsune/src/http/handler/custom_emojis.rs +++ b/kitsune/src/http/handler/custom_emojis.rs @@ -1,6 +1,7 @@ -use crate::{error::Result, http::responder::ActivityPubJson, state::Zustand}; +use crate::{http::responder::ActivityPubJson, state::Zustand}; use axum::{debug_handler, extract::Path, extract::State, routing, Router}; use kitsune_activitypub::mapping::IntoObject; +use kitsune_error::Result; use kitsune_service::custom_emoji::CustomEmojiService; use kitsune_type::ap::emoji::Emoji; use speedy_uuid::Uuid; diff --git a/kitsune/src/http/handler/media.rs b/kitsune/src/http/handler/media.rs index 9a406a071..99920a84f 100644 --- a/kitsune/src/http/handler/media.rs +++ b/kitsune/src/http/handler/media.rs @@ -1,4 +1,4 @@ -use crate::{error::Result, state::Zustand}; +use crate::state::Zustand; use axum::{ body::Body, extract::{Path, State}, @@ -6,6 +6,7 @@ use axum::{ routing, Router, }; use http::header::CONTENT_TYPE; +use kitsune_error::Result; use kitsune_service::attachment::AttachmentService; use speedy_uuid::Uuid; diff --git a/kitsune/src/http/handler/nodeinfo/two_one.rs b/kitsune/src/http/handler/nodeinfo/two_one.rs index 9983c2450..b9b6b647a 100644 --- a/kitsune/src/http/handler/nodeinfo/two_one.rs +++ b/kitsune/src/http/handler/nodeinfo/two_one.rs @@ -1,4 +1,4 @@ -use crate::{error::Result, state::Zustand}; +use crate::state::Zustand; use axum::{debug_handler, extract::State, routing, Json, Router}; use diesel::{ExpressionMethods, QueryDsl}; use diesel_async::RunQueryDsl; @@ -7,6 +7,7 @@ use kitsune_db::{ schema::{posts, users}, with_connection, PgPool, }; +use kitsune_error::Result; use kitsune_service::user::UserService; use kitsune_type::nodeinfo::two_one::{ Protocol, Services, Software, TwoOne, Usage, UsageUsers, Version, diff --git a/kitsune/src/http/handler/oauth/authorize.rs b/kitsune/src/http/handler/oauth/authorize.rs index 78ae3b376..cc0da0c49 100644 --- a/kitsune/src/http/handler/oauth/authorize.rs +++ b/kitsune/src/http/handler/oauth/authorize.rs @@ -1,4 +1,3 @@ -use crate::error::{Error, Result}; use crate::oauth2::{OAuthEndpoint, OAuthOwnerSolicitor}; use argon2::{Argon2, PasswordHash, PasswordVerifier}; use askama::Template; @@ -21,6 +20,7 @@ use diesel::{ExpressionMethods, OptionalExtension, QueryDsl}; use diesel_async::RunQueryDsl; use kitsune_db::with_connection; use kitsune_db::{model::user::User, schema::users, PgPool}; +use kitsune_error::{Error, Result}; use oxide_auth_async::endpoint::authorization::AuthorizationFlow; use oxide_auth_axum::{OAuthRequest, OAuthResponse}; use serde::Deserialize; diff --git a/kitsune/src/http/handler/oauth/token.rs b/kitsune/src/http/handler/oauth/token.rs index 7d5ceeb18..6d9e7a739 100644 --- a/kitsune/src/http/handler/oauth/token.rs +++ b/kitsune/src/http/handler/oauth/token.rs @@ -1,8 +1,6 @@ -use crate::{ - error::{Error, OAuth2Error, Result}, - oauth2::OAuthEndpoint, -}; +use crate::oauth2::OAuthEndpoint; use axum::{debug_handler, extract::State}; +use kitsune_error::{kitsune_error, Error, ErrorType, Result}; use oxide_auth::endpoint::QueryParameter; use oxide_auth_async::endpoint::{ access_token::AccessTokenFlow, client_credentials::ClientCredentialsFlow, refresh::RefreshFlow, @@ -18,7 +16,7 @@ pub async fn post( let grant_type = oauth_req .body() .and_then(|body| body.unique_value("grant_type")) - .ok_or(OAuth2Error::MissingGrantType)?; + .ok_or_else(|| kitsune_error!(type = ErrorType::BadRequest(None), "missing grant type"))?; match grant_type.as_ref() { "authorization_code" => { diff --git a/kitsune/src/http/handler/oidc/callback.rs b/kitsune/src/http/handler/oidc/callback.rs index 0f92faaa7..0bac86d3f 100644 --- a/kitsune/src/http/handler/oidc/callback.rs +++ b/kitsune/src/http/handler/oidc/callback.rs @@ -1,7 +1,4 @@ -use crate::{ - error::{OAuth2Error, Result}, - oauth2::{AuthorisationCode, OAuth2Service}, -}; +use crate::oauth2::{AuthorisationCode, OAuth2Service}; use axum::{ extract::{Query, State}, response::Response, @@ -13,6 +10,7 @@ use kitsune_db::{ schema::{oauth2_applications, users}, with_connection, PgPool, }; +use kitsune_error::Result; use kitsune_oidc::OidcService; use kitsune_service::user::{Register, UserService}; use serde::Deserialize; @@ -67,7 +65,7 @@ pub async fn get( .application(application) .state(user_info.oauth2.state) .user_id(user.id) - .scopes(user_info.oauth2.scope.parse().map_err(OAuth2Error::from)?) + .scopes(user_info.oauth2.scope.parse()?) .build(); oauth_service diff --git a/kitsune/src/http/handler/posts/activity.rs b/kitsune/src/http/handler/posts/activity.rs index 448bf0518..b776ff0ef 100644 --- a/kitsune/src/http/handler/posts/activity.rs +++ b/kitsune/src/http/handler/posts/activity.rs @@ -1,9 +1,10 @@ -use crate::{error::Result, http::responder::ActivityPubJson, state::Zustand}; +use crate::{http::responder::ActivityPubJson, state::Zustand}; use axum::{ debug_handler, extract::{Path, State}, }; use kitsune_activitypub::mapping::IntoActivity; +use kitsune_error::Result; use kitsune_type::ap::Activity; use speedy_uuid::Uuid; diff --git a/kitsune/src/http/handler/posts/mod.rs b/kitsune/src/http/handler/posts/mod.rs index 1161d4aa9..7b4a29f25 100644 --- a/kitsune/src/http/handler/posts/mod.rs +++ b/kitsune/src/http/handler/posts/mod.rs @@ -1,6 +1,7 @@ -use crate::{error::Result, http::responder::ActivityPubJson, state::Zustand}; +use crate::{http::responder::ActivityPubJson, state::Zustand}; use axum::{debug_handler, extract::Path, extract::State, routing, Router}; use kitsune_activitypub::mapping::IntoObject; +use kitsune_error::Result; use kitsune_service::post::PostService; use kitsune_type::ap::Object; use speedy_uuid::Uuid; diff --git a/kitsune/src/http/handler/users/followers.rs b/kitsune/src/http/handler/users/followers.rs index a1732373f..55b1b4016 100644 --- a/kitsune/src/http/handler/users/followers.rs +++ b/kitsune/src/http/handler/users/followers.rs @@ -1,4 +1,4 @@ -use crate::{error::Result, http::responder::ActivityPubJson, state::Zustand}; +use crate::{http::responder::ActivityPubJson, state::Zustand}; use axum::extract::{OriginalUri, Path, State}; use diesel::{BoolExpressionMethods, ExpressionMethods, JoinOnDsl, QueryDsl}; use diesel_async::RunQueryDsl; @@ -6,6 +6,7 @@ use kitsune_db::{ schema::{accounts, accounts_follows}, with_connection, }; +use kitsune_error::Result; use kitsune_type::ap::{ ap_context, collection::{Collection, CollectionType}, diff --git a/kitsune/src/http/handler/users/following.rs b/kitsune/src/http/handler/users/following.rs index 478c01390..39cc10ca6 100644 --- a/kitsune/src/http/handler/users/following.rs +++ b/kitsune/src/http/handler/users/following.rs @@ -1,4 +1,4 @@ -use crate::{error::Result, http::responder::ActivityPubJson, state::Zustand}; +use crate::{http::responder::ActivityPubJson, state::Zustand}; use axum::extract::{OriginalUri, Path, State}; use diesel::{BoolExpressionMethods, ExpressionMethods, JoinOnDsl, QueryDsl}; use diesel_async::RunQueryDsl; @@ -6,6 +6,7 @@ use kitsune_db::{ schema::{accounts, accounts_follows}, with_connection, }; +use kitsune_error::Result; use kitsune_type::ap::{ ap_context, collection::{Collection, CollectionType}, diff --git a/kitsune/src/http/handler/users/inbox.rs b/kitsune/src/http/handler/users/inbox.rs index 3e383080a..39de53694 100644 --- a/kitsune/src/http/handler/users/inbox.rs +++ b/kitsune/src/http/handler/users/inbox.rs @@ -1,19 +1,10 @@ -use crate::{ - error::{Error, Result}, - http::extractor::SignedActivity, - state::Zustand, -}; +use crate::{http::extractor::SignedActivity, state::Zustand}; use axum::{debug_handler, extract::State}; use diesel::{BoolExpressionMethods, ExpressionMethods, QueryDsl, SelectableHelper}; use diesel_async::RunQueryDsl; use iso8601_timestamp::Timestamp; -use kitsune_activitypub::{ - error::Error as ApError, process_new_object, update_object, ProcessNewObject, -}; -use kitsune_core::{ - error::HttpError, - event::{post::EventType, PostEvent}, -}; +use kitsune_activitypub::{process_new_object, update_object, ProcessNewObject}; +use kitsune_core::error::HttpError; use kitsune_db::{ model::{ account::Account, @@ -27,6 +18,7 @@ use kitsune_db::{ schema::{accounts_follows, accounts_preferences, notifications, posts, posts_favourites}, with_connection, }; +use kitsune_error::{Error, Result}; use kitsune_federation_filter::FederationFilter; use kitsune_jobs::deliver::accept::DeliverAccept; use kitsune_service::job::Enqueue; @@ -47,12 +39,7 @@ async fn accept_activity(state: &Zustand, activity: Activity) -> Result<()> { } async fn announce_activity(state: &Zustand, author: Account, activity: Activity) -> Result<()> { - let Some(reposted_post) = state - .fetcher - .fetch_post(activity.object().into()) - .await - .map_err(Error::Fetcher)? - else { + let Some(reposted_post) = state.fetcher.fetch_post(activity.object().into()).await? else { return Err(HttpError::BadRequest.into()); }; @@ -92,47 +79,22 @@ async fn create_activity(state: &Zustand, author: Account, activity: Activity) - .object(Box::new(object)) .search_backend(state.service.search.backend()) .build(); - let new_post = process_new_object(process_data).await?; - - state - .event_emitter - .post - .emit(PostEvent { - r#type: EventType::Create, - post_id: new_post.id, - }) - .await - .map_err(Error::Messaging)?; + process_new_object(process_data).await?; } Ok(()) } async fn delete_activity(state: &Zustand, author: Account, activity: Activity) -> Result<()> { - let post_id = with_connection!(state.db_pool, |db_conn| { - let post_id = posts::table - .filter(posts::account_id.eq(author.id)) - .filter(posts::url.eq(activity.object())) - .select(posts::id) - .get_result(db_conn) - .await?; - - diesel::delete(posts::table.find(post_id)) - .execute(db_conn) - .await?; - - Ok::<_, Error>(post_id) - })?; - - state - .event_emitter - .post - .emit(PostEvent { - r#type: EventType::Delete, - post_id, - }) + with_connection!(state.db_pool, |db_conn| { + diesel::delete( + posts::table + .filter(posts::account_id.eq(author.id)) + .filter(posts::url.eq(activity.object())), + ) + .execute(db_conn) .await - .map_err(Error::Messaging)?; + })?; Ok(()) } @@ -141,8 +103,7 @@ async fn follow_activity(state: &Zustand, author: Account, activity: Activity) - let Some(followed_user) = state .fetcher .fetch_account(activity.object().into()) - .await - .map_err(Error::Fetcher)? + .await? else { return Err(HttpError::BadRequest.into()); }; @@ -298,17 +259,8 @@ async fn update_activity(state: &Zustand, author: Account, activity: Activity) - .object(Box::new(object)) .search_backend(state.service.search.backend()) .build(); - let modified_post = update_object(process_data).await?; - state - .event_emitter - .post - .emit(PostEvent { - r#type: EventType::Update, - post_id: modified_post.id, - }) - .await - .map_err(Error::Messaging)?; + update_object(process_data).await?; } Ok(()) @@ -329,10 +281,7 @@ pub async fn post( let counter = counter!("received_activities"); counter.increment(1); - if !federation_filter - .is_entity_allowed(&activity) - .map_err(ApError::from)? - { + if !federation_filter.is_entity_allowed(&activity)? { return Ok(()); } diff --git a/kitsune/src/http/handler/users/mod.rs b/kitsune/src/http/handler/users/mod.rs index 2d9e5e0f5..f7cc1768e 100644 --- a/kitsune/src/http/handler/users/mod.rs +++ b/kitsune/src/http/handler/users/mod.rs @@ -1,10 +1,11 @@ -use crate::{error::Result, http::responder::ActivityPubJson, state::Zustand}; +use crate::{http::responder::ActivityPubJson, state::Zustand}; use axum::{ extract::{Path, State}, routing, Router, }; use kitsune_activitypub::mapping::IntoObject; use kitsune_core::error::HttpError; +use kitsune_error::Result; use kitsune_service::account::AccountService; use kitsune_type::ap::actor::Actor; use speedy_uuid::Uuid; diff --git a/kitsune/src/http/handler/users/outbox.rs b/kitsune/src/http/handler/users/outbox.rs index ab8a713af..3217e97bf 100644 --- a/kitsune/src/http/handler/users/outbox.rs +++ b/kitsune/src/http/handler/users/outbox.rs @@ -1,4 +1,4 @@ -use crate::{error::Result, http::responder::ActivityPubJson, state::Zustand}; +use crate::{http::responder::ActivityPubJson, state::Zustand}; use axum::extract::{OriginalUri, Path, Query, State}; use axum_extra::either::Either; use diesel::{BelongingToDsl, ExpressionMethods, QueryDsl, SelectableHelper}; @@ -10,6 +10,7 @@ use kitsune_db::{ schema::accounts, with_connection, }; +use kitsune_error::Result; use kitsune_service::account::GetPosts; use kitsune_type::ap::{ ap_context, diff --git a/kitsune/src/http/handler/well_known/webfinger.rs b/kitsune/src/http/handler/well_known/webfinger.rs index 01a5f0049..97cced1c0 100644 --- a/kitsune/src/http/handler/well_known/webfinger.rs +++ b/kitsune/src/http/handler/well_known/webfinger.rs @@ -1,10 +1,11 @@ -use crate::{error::Result, state::Zustand}; +use crate::state::Zustand; use axum::{ extract::{Query, State}, routing, Json, Router, }; use axum_extra::either::Either; use http::StatusCode; +use kitsune_error::Result; use kitsune_service::account::{AccountService, GetUser}; use kitsune_type::webfinger::{Link, Resource}; use kitsune_url::UrlService; @@ -66,7 +67,6 @@ pub fn routes() -> Router { #[cfg(test)] mod tests { use super::{get, WebfingerQuery}; - use crate::error::Error; use athena::JobQueue; use axum::{ extract::{Query, State}, @@ -85,6 +85,7 @@ mod tests { schema::accounts, with_connection_panicky, PgPool, }; + use kitsune_error::Error; use kitsune_federation_filter::FederationFilter; use kitsune_http_client::Client; use kitsune_jobs::KitsuneContextRepo; diff --git a/kitsune/src/http/pagination.rs b/kitsune/src/http/pagination.rs index 113765b18..f40c60b56 100644 --- a/kitsune/src/http/pagination.rs +++ b/kitsune/src/http/pagination.rs @@ -3,10 +3,9 @@ use axum::{ Json, }; use http::{Error as HttpError, HeaderValue}; +use kitsune_error::Error; use std::{borrow::Cow, fmt::Display}; -use crate::error::Error; - pub type PaginatedJsonResponse = ( Option>>, Json>, diff --git a/kitsune/src/http/util.rs b/kitsune/src/http/util.rs index ffbf56c8a..fb35b8136 100644 --- a/kitsune/src/http/util.rs +++ b/kitsune/src/http/util.rs @@ -1,9 +1,8 @@ -use crate::error::Result; use axum::extract::multipart; use bytes::Bytes; use futures_util::{Stream, TryStreamExt}; use kitsune_core::error::HttpError; -use kitsune_storage::BoxError; +use kitsune_error::Result; use std::io::SeekFrom; use tempfile::tempfile; use tokio::{ @@ -15,7 +14,7 @@ use tokio_util::io::ReaderStream; #[allow(dead_code)] // Not used when the Mastodon API feature is deactivated pub async fn buffer_multipart_to_tempfile( field: &mut multipart::Field<'_>, -) -> Result> + Send + 'static> { +) -> Result> + Send + 'static> { let tempfile = tempfile().unwrap(); let mut tempfile = File::from_std(tempfile); diff --git a/kitsune/src/lib.rs b/kitsune/src/lib.rs index 88d789876..882ebb248 100644 --- a/kitsune/src/lib.rs +++ b/kitsune/src/lib.rs @@ -12,7 +12,7 @@ pub mod state; use self::{ oauth2::{OAuth2Service, OAuthEndpoint}, - state::{EventEmitter, Service, SessionConfig, Zustand, ZustandInner}, + state::{Service, SessionConfig, Zustand, ZustandInner}, }; use athena::JobQueue; use color_eyre::eyre;