···162162163163 let updated_jar = jar.add(cookie);
164164165165- // let destination = match oauth_request.destination {
166166- // Some(destination) => destination,
167167- // None => "/".to_string(),
168168- // };
165165+ // Retrieve destination from OAuth request before deleting it
166166+ let postgres_storage = crate::storage::atproto::PostgresOAuthRequestStorage::new(
167167+ web_context.pool.clone()
168168+ );
169169+ let destination = match postgres_storage.get_destination(&callback_state).await {
170170+ Ok(Some(dest)) => dest,
171171+ Ok(None) => "/".to_string(),
172172+ Err(err) => {
173173+ tracing::error!(?err, "Failed to get destination");
174174+ "/".to_string()
175175+ }
176176+ };
177177+178178+ // Delete the OAuth request now that we're done with it
179179+ if let Err(err) = web_context
180180+ .oauth_storage
181181+ .delete_oauth_request_by_state(&callback_state)
182182+ .await
183183+ {
184184+ tracing::error!(error = ?err, "Unable to remove oauth_request");
185185+ }
169186170170- Ok((updated_jar, Redirect::to("/")).into_response())
187187+ Ok((updated_jar, Redirect::to(destination.as_str())).into_response())
171188}
172189173190#[derive(Clone, Deserialize)]
+15-1
src/http/handle_oauth_aip_login.rs
···3333#[derive(Deserialize)]
3434pub(crate) struct OAuthLoginForm {
3535 handle: Option<String>,
3636+ destination: Option<String>,
3637}
37383838-#[derive(Deserialize)]
3939+#[derive(Debug, Deserialize)]
3940pub(crate) struct Destination {
4041 destination: Option<String>,
4142}
···241242 {
242243 tracing::error!(?err, "insert_oauth_request");
243244 return contextual_error!(web_context, language, error_template, default_context, err);
245245+ }
246246+247247+ if let Some(ref dest) = login_form.destination {
248248+ if dest != "/" {
249249+ // Create a direct instance to access the set_destination method
250250+ let postgres_storage = crate::storage::atproto::PostgresOAuthRequestStorage::new(
251251+ web_context.pool.clone()
252252+ );
253253+ if let Err(err) = postgres_storage.set_destination(&state, dest).await {
254254+ tracing::error!(?err, "set_destination");
255255+ // Don't fail the login flow if we can't store the destination
256256+ }
257257+ }
244258 }
245259246260 let oauth_args = [
+13-2
src/http/handle_oauth_callback.rs
···163163164164 let token_response = token_response.unwrap();
165165166166+ // Retrieve destination from OAuth request before deleting it
167167+ let postgres_storage = crate::storage::atproto::PostgresOAuthRequestStorage::new(
168168+ web_context.pool.clone()
169169+ );
170170+ let destination = match postgres_storage.get_destination(&callback_state).await {
171171+ Ok(Some(dest)) => dest,
172172+ Ok(None) => "/".to_string(),
173173+ Err(err) => {
174174+ tracing::error!(?err, "Failed to get destination");
175175+ "/".to_string()
176176+ }
177177+ };
178178+166179 if let Err(err) = web_context
167180 .oauth_storage
168181 .delete_oauth_request_by_state(&callback_state)
···187200 cookie.set_same_site(Some(SameSite::Lax));
188201189202 let updated_jar = jar.add(cookie);
190190-191191- let destination = "/".to_string(); // Simplified for initial pass
192203193204 Ok((updated_jar, Redirect::to(&destination)).into_response())
194205}
+14
src/http/handle_oauth_login.rs
···272272 return contextual_error!(web_context, language, error_template, default_context, err);
273273 }
274274275275+ // Store destination if provided and not "/"
276276+ if let Some(ref dest) = destination.destination {
277277+ if dest != "/" {
278278+ // Create a direct instance to access the set_destination method
279279+ let postgres_storage = crate::storage::atproto::PostgresOAuthRequestStorage::new(
280280+ web_context.pool.clone()
281281+ );
282282+ if let Err(err) = postgres_storage.set_destination(&oauth_request_state.state, dest).await {
283283+ tracing::error!(?err, "set_destination");
284284+ // Don't fail the login flow if we can't store the destination
285285+ }
286286+ }
287287+ }
288288+275289 let oauth_args = [
276290 (
277291 "request_uri".to_string(),
+4
src/http/handle_view_event.rs
···283283284284 let event_url = url_from_aturi(&ctx.web_context.config.external_base, &event.aturi)?;
285285286286+ // Create login URL with destination parameter for this event
287287+ let login_url = format!("/oauth/login?destination={}", urlencoding::encode(&format!("/{}/{}", handle_slug, event_rkey)));
288288+286289 // Add Edit button link if the user is the event creator
287290 let can_edit = ctx
288291 .current_handle
···464467 language => ctx.language.to_string(),
465468 identity_has_email,
466469 canonical_url => event_url,
470470+ login_url => login_url,
467471 event => event_with_counts,
468472 is_self,
469473 can_edit,
···243243 {% elif not current_handle %}
244244 <article class="message">
245245 <div class="message-body">
246246- <a href="{{ base }}/oauth/login">Log in</a> to RSVP to this
246246+ <a href="{{ login_url }}">Log in</a> to RSVP to this
247247 event.
248248 </div>
249249 </article>