4 Commits

Author SHA1 Message Date
7b7554c84b Merge pull request 'mobile update' (#34) from bugfix/iro4ka into master
All checks were successful
Build and Publish Images / build-and-push (push) Successful in 2m8s
Reviewed-on: http://192.168.31.100:3847/Arrelin/family_budget/pulls/34
2026-03-10 14:28:58 +03:00
c884bf812c Merge pull request 'mobile update' (#33) from bugfix/iro4ka into master
All checks were successful
Build and Publish Images / build-and-push (push) Successful in 43s
Reviewed-on: http://192.168.31.100:3847/Arrelin/family_budget/pulls/33
2026-03-10 14:11:49 +03:00
91f9ed5474 Merge pull request 'bugfix/iro4ka' (#32) from bugfix/iro4ka into master
All checks were successful
Build and Publish Images / build-and-push (push) Successful in 2m26s
Reviewed-on: http://192.168.31.100:3847/Arrelin/family_budget/pulls/32
2026-03-10 13:55:40 +03:00
adad656df2 Merge pull request 'bugos' (#31) from bugfix/iro4ka into master
All checks were successful
Build and Publish Images / build-and-push (push) Successful in 2m39s
Reviewed-on: http://192.168.31.100:3847/Arrelin/family_budget/pulls/31
2026-03-10 12:16:13 +03:00
7 changed files with 9 additions and 49 deletions

View File

@@ -27,6 +27,4 @@ reqwest = { version = "0.13.1", features = ["json"] }
rand = "0.9.2" rand = "0.9.2"
uuid = { version = "1", features = ["v4"] } uuid = { version = "1", features = ["v4"] }
sha2 = "0.10" sha2 = "0.10"
hex = "0.4" hex = "0.4"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

View File

@@ -231,7 +231,7 @@ pub async fn create_app(db: DatabaseConnection) -> Result<Router, DbErr> {
.url("/api-docs/openapi.json", ApiDoc::openapi()); .url("/api-docs/openapi.json", ApiDoc::openapi());
let allowed_origins = std::env::var("ALLOWED_ORIGINS") let allowed_origins = std::env::var("ALLOWED_ORIGINS")
.unwrap_or_else(|_| "http://localhost:3000,http://localhost:5173,http://localhost:5174,http://localhost:5175,http://localhost:8080,http://localhost:1420,http://tauri.localhost,https://tauri.localhost".to_string()); .unwrap_or_else(|_| "http://localhost:3000,http://localhost:5173,http://localhost:5174,http://localhost:5175,http://localhost:8080".to_string());
let origins: Vec<HeaderValue> = allowed_origins let origins: Vec<HeaderValue> = allowed_origins
.split(',') .split(',')

View File

@@ -3,13 +3,6 @@ use sea_orm::DbErr;
use sea_orm_migration::prelude::*; use sea_orm_migration::prelude::*;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), DbErr> { async fn main() -> Result<(), DbErr> {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| "family_budget=debug,info".parse().unwrap()),
)
.init();
let db = establish_connection().await?; let db = establish_connection().await?;
println!("Successfully connected to database!"); println!("Successfully connected to database!");

View File

@@ -9,7 +9,6 @@ use sea_orm::{DatabaseConnection, EntityTrait};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use tower_sessions::Session; use tower_sessions::Session;
use tracing::{info, warn};
use utoipa::ToSchema; use utoipa::ToSchema;
use crate::auth::AuthBackend; use crate::auth::AuthBackend;
@@ -117,7 +116,6 @@ pub async fn google_auth(
let nonce = uuid::Uuid::new_v4().to_string(); let nonce = uuid::Uuid::new_v4().to_string();
let mobile_state = make_mobile_csrf_state(&nonce); let mobile_state = make_mobile_csrf_state(&nonce);
let auth_url = oauth_service.get_auth_url_with_state(mobile_state); let auth_url = oauth_service.get_auth_url_with_state(mobile_state);
info!("mobile google_auth: generated signed state for nonce={}", nonce);
return Ok(Json(OAuthUrlResponse { url: auth_url })); return Ok(Json(OAuthUrlResponse { url: auth_url }));
} }
@@ -154,7 +152,6 @@ pub async fn google_callback(
Query(query): Query<GoogleCallbackQuery>, Query(query): Query<GoogleCallbackQuery>,
) -> Result<Response, StatusCode> { ) -> Result<Response, StatusCode> {
let is_mobile = verify_mobile_csrf_state(&query.state); let is_mobile = verify_mobile_csrf_state(&query.state);
info!("google_callback: state={} is_mobile={}", &query.state[..query.state.len().min(20)], is_mobile);
if !is_mobile { if !is_mobile {
let session_csrf: Option<String> = session let session_csrf: Option<String> = session
@@ -165,10 +162,7 @@ pub async fn google_callback(
match session_csrf { match session_csrf {
Some(csrf) if csrf == query.state => {} Some(csrf) if csrf == query.state => {}
_ => { _ => return Err(StatusCode::UNAUTHORIZED),
warn!("google_callback: CSRF mismatch, session_csrf={:?}", session_csrf.as_deref().map(|s| &s[..s.len().min(10)]));
return Err(StatusCode::UNAUTHORIZED);
}
} }
} }
@@ -197,7 +191,6 @@ pub async fn google_callback(
if is_mobile { if is_mobile {
let token = make_auth_token(user.id); let token = make_auth_token(user.id);
info!("google_callback: mobile auth for user_id={}, token_prefix={}", user.id, &token[..token.len().min(20)]);
let deep_link = format!("com.arrelin.family-budget-android://auth?token={}", token); let deep_link = format!("com.arrelin.family-budget-android://auth?token={}", token);
let html = format!( let html = format!(
r#"<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0;url={0}"></head><body><script>window.location="{0}"</script></body></html>"#, r#"<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0;url={0}"></head><body><script>window.location="{0}"</script></body></html>"#,
@@ -238,15 +231,7 @@ pub async fn mobile_callback(
State(db): State<DatabaseConnection>, State(db): State<DatabaseConnection>,
Query(query): Query<MobileCallbackQuery>, Query(query): Query<MobileCallbackQuery>,
) -> Result<Json<serde_json::Value>, StatusCode> { ) -> Result<Json<serde_json::Value>, StatusCode> {
info!("mobile_callback: received token_prefix={}", &query.token[..query.token.len().min(20)]); let user_id = verify_auth_token(&query.token).ok_or(StatusCode::UNAUTHORIZED)?;
let user_id = match verify_auth_token(&query.token) {
Some(id) => id,
None => {
warn!("mobile_callback: token verification failed for token={}", &query.token[..query.token.len().min(40)]);
return Err(StatusCode::UNAUTHORIZED);
}
};
info!("mobile_callback: token valid for user_id={}", user_id);
let user = User::find_by_id(user_id) let user = User::find_by_id(user_id)
.one(&db) .one(&db)

View File

@@ -30,20 +30,18 @@ export default function Login() {
try { try {
token = new URL(url).searchParams.get('token'); token = new URL(url).searchParams.get('token');
} catch { } catch {
setError(t('login.authError')); setError(t('login.error'));
return; return;
} }
if (!token) { setError(t('login.authError')); return; } if (!token) { setError(t('login.error')); return; }
try { try {
setLoading(true); setLoading(true);
await authApi.mobileCallback(token); await authApi.mobileCallback(token);
const me = await authApi.me(); const me = await authApi.me();
setUser(me.data); setUser(me.data);
} catch (err: any) { } catch {
const status = err?.response?.status; setError(t('login.error'));
const msg = err?.response?.data ? JSON.stringify(err.response.data) : err?.message;
setError(`${status ?? 'network'}: ${msg}`);
setLoading(false); setLoading(false);
} }
}); });

View File

@@ -12,20 +12,6 @@ export default defineConfig({
? 'https://family-budget.duckdns.org' ? 'https://family-budget.duckdns.org'
: 'http://localhost:8080', : 'http://localhost:8080',
changeOrigin: true, changeOrigin: true,
configure: (proxy) => {
if (process.env.TAURI_DEV_HOST) {
proxy.on('proxyRes', (proxyRes) => {
const cookies = proxyRes.headers['set-cookie'];
if (cookies) {
proxyRes.headers['set-cookie'] = cookies.map(cookie =>
cookie
.replace(/;\s*Secure/gi, '')
.replace(/;\s*Domain=[^;]*/gi, '')
);
}
});
}
},
} }
} }
} }

View File

@@ -6,7 +6,7 @@
"build": { "build": {
"beforeDevCommand": "npm run dev --prefix ../frontend", "beforeDevCommand": "npm run dev --prefix ../frontend",
"devUrl": "http://localhost:5173", "devUrl": "http://localhost:5173",
"beforeBuildCommand": "VITE_API_BASE_URL=https://family-budget.duckdns.org/api npm run build --prefix ../frontend", "beforeBuildCommand": "npm run build --prefix ../frontend",
"frontendDist": "../frontend/dist" "frontendDist": "../frontend/dist"
}, },
"app": { "app": {