Self-hosted, federated location sharing app and server that prioritizes user privacy and security
end-to-end-encryption location-sharing privacy self-hosted federated

fixed auth deserializing and other small stuff

azom.dev ffbf2082 fed44e4a

verified
Changed files
+10 -23
app
src
home-page
settings-page
utils
server
+2 -2
app/src/home-page/home.ts
··· 1 1 import Alpine from "alpinejs"; 2 2 import { goto } from "../utils/tools.ts"; 3 3 import { Store } from "../utils/store.ts"; 4 - import { generateSignupKey } from "../utils/api.ts"; 4 + import * as api from "../utils/api.ts"; 5 5 6 6 Alpine.data("homePageState", () => ({ 7 7 friends: [ ··· 32 32 }, 33 33 34 34 async generateSignupKey() { 35 - this.newSignupKey = await generateSignupKey(); 35 + this.newSignupKey = await api.generateSignupKey(); 36 36 }, 37 37 38 38 isAdmin() {
+2 -8
app/src/settings-page/settings.html
··· 8 8 9 9 <body> 10 10 <div class="card"> 11 - <!-- x-data connects this element to the settingsPageState Alpine component, enabling its data (serverAddress and signupKey) and functions (signup and scanQR) to work within it :) --> 12 - <!-- TODO: make this a form instead? --> 13 11 <div class="actions" x-data="settingsPageState"> 14 12 <h3>Settings</h3> 15 13 16 - <button class="btn-secondary" @click="goto('home')"> 17 - Back to Home 18 - </button> 14 + <button class="btn-secondary" @click="goto('home')">Back to Home</button> 19 15 20 - <button class="btn-secondary" @click="resetStore()"> 21 - Signout 22 - </button> 16 + <button class="btn-secondary" @click="await debugLogout()">Signout</button> 23 17 </div> 24 18 </div> 25 19 </body>
+2 -3
app/src/settings-page/settings.ts
··· 3 3 import { goto } from "../utils/tools.ts"; 4 4 5 5 Alpine.data("settingsPageState", () => ({ 6 - resetStore() { 7 - Store.reset(); 8 - alert("Store reset"); 6 + async debugLogout() { 7 + await Store.reset(); 9 8 goto("signup"); 10 9 }, 11 10 goto(newLocation: string) {
+1
app/src/utils/api.ts
··· 32 32 return json; 33 33 } 34 34 35 + // this api is laughably vulnerable to a replay attack currently, but not later with key chaining 35 36 export async function generateSignupKey(): Promise<string> { 36 37 return await post("generate-signup-key"); 37 38 }
+1 -8
server/src/auth.rs
··· 27 27 .and_then(|v| v.to_str().ok()) 28 28 .ok_or(SrvErr!("missing x-auth header"))?; 29 29 30 - let decoded_auth = BASE64_STANDARD 31 - .decode(auth_header) 32 - .map_err(|e| SrvErr!("invalid base64 in x-auth header", e))?; 33 - 34 - let auth_str = String::from_utf8(decoded_auth) 35 - .map_err(|e| SrvErr!("invalid utf8 in x-auth header", e))?; 36 - 37 - let auth_data: AuthData = serde_json::from_str(&auth_str) 30 + let auth_data: AuthData = serde_json::from_str(auth_header) 38 31 .map_err(|e| SrvErr!("failed to parse x-auth JSON", e))?; 39 32 40 33 let users = state.users.lock().await;
+2 -2
server/src/main.rs
··· 58 58 .route("/send-pings", post(send_pings)) 59 59 .route("/get-pings", post(get_pings)) 60 60 .with_state(state.clone()) 61 - .layer(CorsLayer::permissive()) 62 61 .layer(axum::middleware::from_fn_with_state(state, auth_test)) 63 - .layer(axum::middleware::from_fn(log_req_res_bodies)); 62 + .layer(axum::middleware::from_fn(log_req_res_bodies)) 63 + .layer(CorsLayer::permissive()); 64 64 65 65 let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); 66 66 axum::serve(listener, app).await.unwrap();