APIs for links and references in the ATmosphere

anon auto-flow

whatever

+70 -9
+1
who-am-i/src/identity_resolver.rs
··· 11 11 http_client: Arc::clone(&http_client), 12 12 }); 13 13 let doc = resolver.resolve(&Did::new(did).unwrap()).await.unwrap(); // TODO: this is only half the resolution? or is atrium checking dns? 14 + // tokio::time::sleep(std::time::Duration::from_secs(2)).await; 14 15 doc.also_known_as.and_then(|mut aka| { 15 16 if aka.is_empty() { 16 17 None
+20 -7
who-am-i/src/server.rs
··· 12 12 use handlebars::{Handlebars, handlebars_helper}; 13 13 14 14 use serde::Deserialize; 15 - use serde_json::{Value, json}; 15 + use serde_json::json; 16 16 use std::sync::Arc; 17 17 use std::time::Duration; 18 18 use tokio::net::TcpListener; ··· 49 49 hbs.register_templates_directory("templates", Default::default()) 50 50 .unwrap(); 51 51 52 - handlebars_helper!(json: |v: Value| serde_json::to_string(&v).unwrap()); 52 + handlebars_helper!(json: |v: String| serde_json::to_string(&v).unwrap()); 53 53 hbs.register_helper("json", Box::new(json)); 54 54 55 55 // clients have to pick up their identity-resolving tasks within this period ··· 110 110 let task_shutdown = shutdown.child_token(); 111 111 let fetch_key = resolving.dispatch(resolve_identity(did.clone()), task_shutdown); 112 112 113 - let json_did = Value::String(did); 114 - let json_fetch_key = Value::String(fetch_key); 115 113 RenderHtml( 116 114 "prompt-known", 117 115 engine, 118 116 json!({ 119 - "did": json_did, 120 - "fetch_key": json_fetch_key, 117 + "did": did, 118 + "fetch_key": fetch_key, 121 119 "parent_host": parent_host, 122 120 }), 123 121 ) ··· 183 181 panic!("failed to do client callback"); 184 182 }; 185 183 let did = oauth_session.did().await.expect("a did to be present"); 184 + 186 185 let cookie = Cookie::build((DID_COOKIE_KEY, did.to_string())) 187 186 .http_only(true) 188 187 .secure(true) 189 188 .same_site(SameSite::None) 190 189 .max_age(std::time::Duration::from_secs(86_400).try_into().unwrap()); 190 + 191 191 let jar = jar.add(cookie); 192 + 193 + let task_shutdown = state.shutdown.child_token(); 194 + let fetch_key = state 195 + .resolving 196 + .dispatch(resolve_identity(did.to_string()), task_shutdown); 197 + 192 198 ( 193 199 jar, 194 - RenderHtml("authorized", state.engine, json!({ "did": did })), 200 + RenderHtml( 201 + "authorized", 202 + state.engine, 203 + json!({ 204 + "did": did, 205 + "fetch_key": fetch_key, 206 + }), 207 + ), 195 208 ) 196 209 }
+5 -1
who-am-i/templates/authorized.hbs
··· 4 4 5 5 <script> 6 6 // TODO: tie this back to its source........... 7 - localStorage.setItem("did", {{{json did}}}); 7 + 8 + localStorage.setItem("who-am-i", JSON.stringify({ 9 + did: {{{json did}}}, 10 + fetch_key: {{{json fetch_key}}}, 11 + })); 8 12 window.close(); 9 13 </script>
+44 -1
who-am-i/templates/prompt-anon.hbs
··· 4 4 <span class="parent-host">{{ parent_host }}</span>? 5 5 </p> 6 6 7 + <div id="loader" class="hidden"> 8 + <span class="spinner"></span> 9 + </div> 10 + 7 11 <div id="user-info"> 8 12 <form id="action" action="/auth" method="GET" target="_blank"> 9 13 <label> ··· 14 18 </div> 15 19 16 20 <script> 21 + var loaderEl = document.getElementById('loader'); 22 + var infoEl = document.getElementById('user-info'); 17 23 const formEl = document.getElementById('action'); 18 24 const handleEl = document.getElementById('handle'); 25 + 19 26 formEl.onsubmit = e => { 20 27 e.preventDefault(); 21 28 // TODO: include expected referer! (..this system is probably bad) 29 + // maybe a random localstorage key that we specifically listen for? 22 30 var url = new URL('/auth', window.location); 23 31 url.searchParams.set('handle', handleEl.value); 24 32 var flow = window.open(url, '_blank'); 25 33 window.f = flow; 26 34 27 35 window.addEventListener('storage', e => { 28 - location.reload(); 36 + var details = localStorage.getItem("who-am-i"); 37 + if (!details) { 38 + console.error("hmm, heard from localstorage but did not get DID"); 39 + } 40 + var parsed = JSON.parse(details); 41 + 42 + infoEl.classList.add('hidden'); 43 + loaderEl.classList.remove('hidden'); 44 + lookUpAndShare(parsed.fetch_key); 29 45 }); 30 46 } 47 + 48 + function lookUpAndShare(fetch_key) { 49 + let user_info = new URL('/user-info', window.location); 50 + user_info.searchParams.set('fetch-key', fetch_key); 51 + fetch(user_info) 52 + .then(resp => { 53 + if (!resp.ok) throw new Error('request failed'); 54 + return resp.json(); 55 + }) 56 + .then( 57 + ({ handle }) => { 58 + loaderEl.remove(); 59 + handleEl.textContent = `@${handle}`; 60 + infoEl.classList.remove('hidden'); 61 + share(handle); 62 + }, 63 + err => { 64 + infoEl.textContent = 'ohno'; 65 + console.error(err); 66 + }, 67 + ); 68 + } 69 + 70 + function share(handle) { 71 + top.postMessage({ source: 'whoami', handle }, '*'); // TODO: pass the referrer back from server 72 + } 73 + 31 74 </script> 32 75 {{/inline}} 33 76