···187187 did: &str,
188188 expected_handle: Option<String>,
189189) -> eyre::Result<Option<Option<String>>> {
190190+ // Resolve the did doc
190191 let Some(did_doc) = state.resolver.resolve_did(did).await? else {
191192 eyre::bail!("missing did doc");
192193 };
193194194194- let Some(handle) = did_doc
195195- .also_known_as
196196- .and_then(|aka| aka.first().cloned())
197197- .and_then(|handle| handle.strip_prefix("at://").map(String::from))
198198- else {
199199- eyre::bail!("DID doc contained no handle");
200200- };
195195+ // if there's no handles in aka or the expected is none, set to none in DB.
196196+ if did_doc.also_known_as.as_ref().is_none_or(|v| v.is_empty()) || expected_handle.is_none() {
197197+ return Ok(Some(None));
198198+ }
199199+200200+ let expected = expected_handle.unwrap();
201201+202202+ // check if the handle from the event is in the did doc
203203+ let expected_in_doc = did_doc.also_known_as.is_some_and(|v| {
204204+ v.iter()
205205+ .filter_map(|v| v.strip_prefix("at://"))
206206+ .find(|v| v == &expected)
207207+ .is_some()
208208+ });
209209+210210+ // if it isn't, set to invalid.
211211+ if !expected_in_doc {
212212+ tracing::warn!("Handle not in DID doc");
213213+ return Ok(Some(None));
214214+ }
201215202216 // in theory, we can use com.atproto.identity.resolveHandle against a PDS, but that seems
203217 // like a way to end up with really sus handles.
204204- let Some(handle_did) = state.resolver.resolve_handle(&handle).await? else {
205205- eyre::bail!("Failed to resolve did for handle {handle}");
218218+ let Some(handle_did) = state.resolver.resolve_handle(&expected).await? else {
219219+ Ok(Some(None))
206220 };
207221222222+ // finally, check if the event did matches the handle, if not, set invalid, otherwise set the handle.
208223 if handle_did != did {
209209- Ok(None)
224224+ Ok(Some(None))
210225 } else {
211211- Ok(Some(expected_handle))
226226+ Ok(Some(Some(expected)))
212227 }
213228}
214229