2 Commits

Author SHA1 Message Date
1f869518be Update dependency dart to v3.11.0
Some checks failed
renovate/artifacts Artifact file update failure
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2026-02-20 00:17:44 +00:00
e74d794d08 Updated project dependencies
Some checks failed
continuous-integration/drone/push Build is failing
2026-02-19 17:50:54 +01:00
8 changed files with 1174 additions and 913 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -4,36 +4,35 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
env_logger = "0.11.8" env_logger = "0.11.9"
log = "0.4.29" log = "0.4.29"
diesel = { version = "2.2.12", features = ["postgres", "r2d2"] } diesel = { version = "2.3.6", features = ["postgres", "r2d2"] }
diesel_migrations = "2.2.0" diesel_migrations = "2.2.0"
clap = { version = "4.5.59", features = ["env", "derive"] } clap = { version = "4.5.59", features = ["env", "derive"] }
actix-web = "4.11.0" actix-web = "4.13.0"
actix-cors = "0.7.1" actix-cors = "0.7.1"
actix-multipart = "0.7.2" actix-multipart = "0.7.2"
actix-remote-ip = "0.1.0" actix-remote-ip = "0.1.0"
actix-session = { version = "0.10.1", features = ["redis-session"] } actix-session = { version = "0.11.0", features = ["redis-session"] }
actix-files = "0.6.10" actix-files = "0.6.10"
lazy_static = "1.5.0"
anyhow = "1.0.101" anyhow = "1.0.101"
serde = { version = "1.0.228", features = ["derive"] } serde = { version = "1.0.228", features = ["derive"] }
rust-s3 = "0.36.0-beta.2" rust-s3 = "0.37.1"
thiserror = "2.0.18" thiserror = "2.0.18"
tokio = "1.45.1" tokio = "1.49.0"
futures-util = "0.3.31" futures-util = "0.3.32"
serde_json = "1.0.149" serde_json = "1.0.149"
light-openid = "1.0.4" light-openid = "1.1.0"
rand = "0.9.2" rand = "0.10.0"
ipnet = { version = "2.11.0", features = ["serde"] } ipnet = { version = "2.11.0", features = ["serde"] }
lazy-regex = "3.4.2" lazy-regex = "3.6.0"
jwt-simple = { version = "0.12.14", default-features = false, features = ["pure-rust"] } jwt-simple = { version = "0.12.14", default-features = false, features = ["pure-rust"] }
mime_guess = "2.0.5" mime_guess = "2.0.5"
rust-embed = { version = "8.7.2" } rust-embed = { version = "8.11.0" }
sha2 = "0.11.0-rc.4" sha2 = "0.11.0-rc.5"
base16ct = "0.2.0" base16ct = { version = "1.0.0", features = ["alloc"] }
httpdate = "1.0.3" httpdate = "1.0.3"
chrono = "0.4.43" chrono = "0.4.43"
tempfile = "3.20.0" tempfile = "3.25.0"
zip = "3.0.0" zip = "8.1.0"
rust_xlsxwriter = "0.87.0" rust_xlsxwriter = "0.93.0"

View File

@@ -1,6 +1,7 @@
use clap::Parser; use clap::Parser;
use s3::creds::Credentials; use s3::creds::Credentials;
use s3::{Bucket, Region}; use s3::{Bucket, Region};
use std::sync::OnceLock;
/// Money Manager backend API /// Money Manager backend API
#[derive(Parser, Debug, Clone)] #[derive(Parser, Debug, Clone)]
@@ -132,16 +133,13 @@ pub struct AppConfig {
pub apk_download_url: String, pub apk_download_url: String,
} }
lazy_static::lazy_static! { /// Cached application config
static ref ARGS: AppConfig = { static ARGS: OnceLock<AppConfig> = OnceLock::new();
AppConfig::parse()
};
}
impl AppConfig { impl AppConfig {
/// Get parsed command line arguments /// Get parsed command line arguments
pub fn get() -> &'static AppConfig { pub fn get() -> &'static AppConfig {
&ARGS ARGS.get_or_init(AppConfig::parse)
} }
/// Get auto login email (if not empty) /// Get auto login email (if not empty)

View File

@@ -2,8 +2,7 @@ use crate::app_config::AppConfig;
use diesel::PgConnection; use diesel::PgConnection;
use diesel::r2d2::{ConnectionManager, Pool, PooledConnection}; use diesel::r2d2::{ConnectionManager, Pool, PooledConnection};
use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations}; use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations};
use lazy_static::lazy_static; use std::sync::{Arc, OnceLock};
use std::sync::Arc;
const MIGRATIONS: EmbeddedMigrations = embed_migrations!(); const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
@@ -20,12 +19,13 @@ fn get_db_connection_pool() -> anyhow::Result<DBConn> {
)) ))
} }
lazy_static! { static DB_POOL: OnceLock<DBConn> = OnceLock::new();
static ref DB_POOL: DBConn = get_db_connection_pool().expect("Failed to connect to database");
}
pub fn db() -> anyhow::Result<PooledConnection<ConnectionManager<PgConnection>>> { pub fn db() -> anyhow::Result<PooledConnection<ConnectionManager<PgConnection>>> {
Ok(DB_POOL.clone().get()?) Ok(DB_POOL
.get_or_init(|| get_db_connection_pool().expect("Failed to connect to database"))
.clone()
.get()?)
} }
pub fn initialize_conn() -> anyhow::Result<()> { pub fn initialize_conn() -> anyhow::Result<()> {

View File

@@ -1,5 +1,5 @@
use crate::app_config::AppConfig; use crate::app_config::AppConfig;
use crate::controllers::{HttpFailure, HttpResult}; use crate::controllers::HttpResult;
use crate::extractors::auth_extractor::{AuthExtractor, AuthenticatedMethod}; use crate::extractors::auth_extractor::{AuthExtractor, AuthenticatedMethod};
use crate::extractors::money_session::MoneySession; use crate::extractors::money_session::MoneySession;
use crate::services::{tokens_service, users_service}; use crate::services::{tokens_service, users_service};
@@ -61,9 +61,7 @@ pub async fn finish_oidc(
let prov = AppConfig::get().openid_provider(); let prov = AppConfig::get().openid_provider();
let conf = OpenIDConfig::load_from_url(prov.configuration_url) let conf = OpenIDConfig::load_from_url(prov.configuration_url).await?;
.await
.map_err(HttpFailure::OpenID)?;
let (token, _) = conf let (token, _) = conf
.request_token( .request_token(
@@ -72,12 +70,8 @@ pub async fn finish_oidc(
&req.code, &req.code,
&AppConfig::get().oidc_redirect_url(), &AppConfig::get().oidc_redirect_url(),
) )
.await .await?;
.map_err(HttpFailure::OpenID)?; let (user_info, _) = conf.request_user_info(&token).await?;
let (user_info, _) = conf
.request_user_info(&token)
.await
.map_err(HttpFailure::OpenID)?;
if user_info.email_verified != Some(true) { if user_info.email_verified != Some(true) {
log::error!("Email is not verified!"); log::error!("Email is not verified!");

View File

@@ -1,7 +1,7 @@
use crate::controllers::backup_controller::BackupControllerError; use crate::controllers::backup_controller::BackupControllerError;
use actix_web::http::StatusCode; use actix_web::http::StatusCode;
use actix_web::{HttpResponse, ResponseError}; use actix_web::{HttpResponse, ResponseError};
use std::error::Error; use light_openid::errors::OpenIdError;
use zip::result::ZipError; use zip::result::ZipError;
pub mod accounts_controller; pub mod accounts_controller;
@@ -28,7 +28,7 @@ pub enum HttpFailure {
#[error("an unhandled session error occurred")] #[error("an unhandled session error occurred")]
SessionError(#[from] actix_session::SessionGetError), SessionError(#[from] actix_session::SessionGetError),
#[error("an unspecified open id error occurred: {0}")] #[error("an unspecified open id error occurred: {0}")]
OpenID(Box<dyn Error>), OpenID(#[from] OpenIdError),
#[error("an unspecified internal error occurred: {0}")] #[error("an unspecified internal error occurred: {0}")]
InternalError(#[from] anyhow::Error), InternalError(#[from] anyhow::Error),
#[error("a serde_json error occurred: {0}")] #[error("a serde_json error occurred: {0}")]

View File

@@ -7,3 +7,20 @@ pub fn sha512(bytes: &[u8]) -> String {
let h = hasher.finalize(); let h = hasher.finalize();
base16ct::lower::encode_string(h.as_slice()) base16ct::lower::encode_string(h.as_slice())
} }
#[cfg(test)]
mod tests {
use crate::utils::crypt_utils::sha512;
#[test]
fn test_sha512() {
assert_eq!(
sha512(&[]),
"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
);
assert_eq!(
sha512("hello".as_bytes()),
"9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043"
);
}
}

View File

@@ -19,7 +19,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1 version: 1.0.0+1
environment: environment:
sdk: ^3.8.1 sdk: 3.11.0
# Dependencies specify other packages that your package needs in order to work. # Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions # To automatically upgrade your package dependencies to the latest versions