mize daemon service and some timetrack stuff as well

This commit is contained in:
Sebastian Moser
2026-05-14 07:43:47 +02:00
parent 193c3ce3e0
commit 55c85ad716
9 changed files with 167 additions and 17 deletions

View File

@@ -43,7 +43,7 @@ let
};
in {
in rec {
############################## PACKAGES ##############################
packages = rec {
@@ -109,6 +109,52 @@ in {
libsoup_3
];
};
mize = osCrane.buildPackage {
src = fileSetForCrate ./packages/mize;
cargoExtraArgs = "-p mize";
nativeBuildInputs = [
pkgs.pkg-config
pkgs.gobject-introspection
pkgs.gobject-introspection.dev
];
buildInputs = with pkgs; [
git # needed to build spacetimedb as it needs to get it's git hash for setting it's version
at-spi2-atk
atkmm
cairo
gdk-pixbuf
glib
gtk3
harfbuzz
librsvg
libsoup_3
pango
webkitgtk_4_1
openssl
wasm-bindgen-cli
lld_20
xdotool
];
LD_LIBRARY_PATH = with pkgs; pkgs.lib.makeLibraryPath [
xdotool
webkitgtk_4_1
pango
openssl
at-spi2-atk
atkmm
cairo
gdk-pixbuf
glib
gtk3
harfbuzz
librsvg
libsoup_3
];
};
};
############################## DEV SHELLS ##############################
@@ -265,6 +311,49 @@ in {
};
};
############################## NIXOS MODULES ##############################
nixosModules.default = { system, lib, config, ... }: {
options.mize = {
debuginary = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/home/user/here/mize";
description = "If set to NOT null, the mize daemon service will use this path instead of $${self.packages.system.mize}/bin/mize''";
};
debugConfigFile = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/home/user/here/mize.toml";
description = "If set to NOT null, the mize daemon service will use the config file at this path instead of one written to the nix store";
};
config = lib.mkOption {
type = lib.types.attrsOf lib.types.anything;
default = {};
example = {
dat_dir = "home/user/my_mize_data";
spacetime.url = "spacetime.example.com";
};
description = "mize config for the daemon";
};
};
systemd.user.services.mize = {
description = "the mize daemon";
wantedBy = [ "default.target" ];
After = [ "graphical-session.target" ];
PartOf = [ "graphical-session.target" ]; # this should mean DISPLAY and WAYLAND_DISPLAY are set in the service env...
environment = {
MIZE_CONFIG_FILES = let fileInStore = (pkgs.formats.toml {}).generate "mize-daemon-config.toml" config.mize.config; in if config.mize.debugConfigFile then "${config.mize.debugConfigFile}" else "${fileInStore}";
};
serviceConfig = {
Restart = "on-failure";
ExecStart = if config.mize.debuginary == null then "${self.packages.${system}.mize}/bin/mize daemon" else "${config.mize.debugBinary} daemon";
};
};
};
# for what we do the nixos and home-manager api is identical
homeModules.default = nixosModules.default;
}) // {
############################## SOME GLOBAL OUTPUTS ##############################

8
md
View File

@@ -30,12 +30,12 @@ function deploy_lush {
if ! tmux has-session -t ppc-deploy 2>/dev/null; then
echo "Created new tmux session...."
tmux new-session -d -s ppc-deploy "nix develop git+file:///home/me/here/mize#buildShell"
tmux send-keys -t ppc-deploy "cargo build --featuers desktop --manifest-path /home/me/here/mize/packages/ppc/Cargo.toml" Enter
tmux send-keys -t ppc-deploy "systemctl --user restart ppc" Enter
tmux send-keys -t ppc-deploy "cargo build --featuers desktop --manifest-path /home/me/here/mize/packages/mize/Cargo.toml" Enter
tmux send-keys -t ppc-deploy "systemctl --user restart mize" Enter
else
echo "using existing session..."
tmux send-keys -t ppc-deploy "cargo build --features desktop --manifest-path /home/me/here/mize/packages/ppc/Cargo.toml" Enter
tmux send-keys -t ppc-deploy "systemctl --user restart ppc" Enter
tmux send-keys -t ppc-deploy "cargo build --features desktop --manifest-path /home/me/here/mize/packages/mize/Cargo.toml" Enter
tmux send-keys -t ppc-deploy "systemctl --user restart mize" Enter
fi
EOF

View File

@@ -66,9 +66,13 @@ pub fn mount(sub_matches: &ArgMatches) -> MizeResult<()> {
Ok(())
}
pub fn run(sub_matches: &ArgMatches) -> MizeResult<()> {
pub fn daemon(sub_matches: &ArgMatches) -> MizeResult<()> {
let instance = Mize::with_config(config_from_cli_args(sub_matches)?)?;
// load all parts we need for any mize application... making a fat daemon for now.
// in the future parts should be loaded on demand (from .so files and from parts.mize.works)
ppc
instance.wait();
return Ok(());

View File

@@ -39,7 +39,7 @@ fn main() {
// match command
let result = match cli_matches.subcommand() {
// mi daemon
Some(("run", sub_matches)) => cli::run(sub_matches),
Some(("daemon", sub_matches)) => cli::run(sub_matches),
Some(("is-running", sub_matches)) => cli::is_running(sub_matches),
@@ -130,11 +130,7 @@ fn cli_matches() -> clap::ArgMatches {
.help("specify a config file")
.global(true),
)
.subcommand(
Command::new("run")
.aliases(["r"])
.about("Run a MiZe Instance"),
)
.subcommand(Command::new("daemon").about("Run a MiZe Instance as a daemon"))
.subcommand(Command::new("stop").about("Stop a MiZe Instance"))
.subcommand(Command::new("mount").aliases(["m"]))
.subcommand(

View File

@@ -47,12 +47,12 @@ path = "lib.rs"
name = "ppc"
[features]
default = ["target-os", "server", "client", "desktop"]
default = ["target-os", "server", "client" ]
target-os = [ "clap", "mize/target-os", "marts/target-os", "tracing", "webbrowser", "base64", "serde_json", "serde" ]
target-obsidian = [ "js-sys", "wasm-bindgen", "mize/target-js", "marts/target-js", "base64", "serde_json", "serde", "openidconnect", "dioxus", "dioxus-web", "web-sys", "web-sys/Document", "dioxus/web" ]
server = [ "axum", "axum-extra", "openidconnect", "serde", "serde_json", "reqwest", "rand", "url", "time", "tokio", "dioxus/ssr", "dioxus/server", "dioxus/fullstack", "dioxus/router", "dioxus-ssr", "html-escape", "axum-oidc", "tower", "tower-sessions", "marts/server", "target-os" ]
desktop = ["dioxus/desktop", "marts/desktop", "target-os"]
client = []
client = [ "tokio", "openidconnect" ]
webbrowser = ["dep:webbrowser"]

View File

@@ -3,6 +3,7 @@ use base64::{
alphabet::STANDARD,
engine::{DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig},
};
use chrono::{DateTime, Local, NaiveDateTime, TimeDelta, Utc};
use dioxus::{fullstack::ClientResponse, html::ol};
use mize::{Mize, MizeError, MizePart, MizeResult, item::ItemData, mize_err, mize_part};
use openidconnect::{
@@ -52,6 +53,7 @@ pub struct ClientSecrets {
id_token: String,
access_token: String,
refresh_token: String,
expiry: DateTime<Utc>,
}
impl MizePart for ClientAuth {
@@ -97,7 +99,14 @@ impl ClientAuth {
let mut mize_clone = self.mize.clone();
self.mize.spawn_background("auth.refresh", move || {
loop {
thread::sleep(Duration::from_hours(23));
let auth = mize_clone.get_part_native::<ClientAuth>("auth")?;
let to_sleep = Utc::now()
- auth.secrets.as_ref().unwrap().expiry.clone()
- TimeDelta::minutes(20);
drop(auth);
println!("refresh_thread: going to sleep for: {}", to_sleep);
thread::sleep(to_sleep.to_std()?);
println!("refresh_thread: sleeping done");
let mut auth = mize_clone.get_part_native::<ClientAuth>("auth")?;
auth.refresh()?;
drop(auth);
@@ -118,6 +127,13 @@ pub fn client_auth(mize: &mut Mize) -> MizeResult<()> {
}
};
// do a refresh if the tokens have expired
if (secrets.is_some() && secrets.unwrap().expiry < Utc::now()) {
secrets = Some(
mize.spawn_async_blocking("refresh_low", refresh_flow(mize.clone(), secrets.unwrap()))?,
);
}
#[cfg(feature = "target-os")]
{
let mut cli = mize.get_part_native::<marts::CliPart>("cli")?;
@@ -260,11 +276,15 @@ async fn refresh_flow(mut mize: Mize, old_secrets: ClientSecrets) -> MizeResult<
.exchange_refresh_token(&refresh_token)?
.request_async(&http_client)
.await?;
let expires_in = res.expires_in().ok_or(mize_err!(
"no expiry information was in token response of the refresh flow"
))?;
return Ok(ClientSecrets {
id_token: res.id_token().unwrap().to_string(),
access_token: res.access_token().secret().to_owned(),
refresh_token: res.refresh_token().unwrap().secret().to_owned(),
expiry: Utc::now() + expires_in,
});
}
@@ -378,10 +398,15 @@ async fn auth_flow(mut mize: Mize) -> MizeResult<ClientSecrets> {
.refresh_token()
.ok_or(mize_err!("no refresh token present"))?;
let expires_in = token_response.expires_in().ok_or(mize_err!(
"no expiry information was in token response of the refresh flow"
))?;
Ok(ClientSecrets {
id_token: id_token.to_string(),
access_token: token_response.access_token().secret().to_string(),
refresh_token: refresh.secret().to_owned(),
expiry: Utc::now() + expires_in,
})
}

View File

@@ -6,17 +6,22 @@ mod platform {
#[cfg(feature = "target-os")]
pub mod os {
#[cfg(feature = "server")]
pub mod server;
#[cfg(feature = "desktop")]
pub mod ui;
}
}
#[cfg(feature = "target-os")]
#[cfg(feature = "website")]
mod website;
#[cfg(feature = "target-os")]
#[cfg(feature = "server")]
pub use platform::os::server::server;
#[cfg(feature = "target-os")]
#[cfg(feature = "desktop")]
pub use platform::os::ui;
pub mod auth {

View File

@@ -1,3 +1,6 @@
use axum::{Json, http::StatusCode};
use serde_json::{Value, json};
use std::net::SocketAddr;
use std::str::FromStr;
use axum::{
@@ -108,7 +111,10 @@ pub async fn start_server(mize: &mut Mize) -> MizeResult<()> {
.layer(tower_http::trace::TraceLayer::new_for_http())
// not authenticated routes
.route("/", get(ppc_main_page))
.route("/oidc_display_code_and_state", get(display_code_and_state));
.route("/oidc_display_code_and_state", get(display_code_and_state))
// .well-known routes for matrix
.route("/.well-known/matrix/server", get(well_known_matrix_server))
.route("/.well-known/matrix/client", get(well_known_matrix_client));
tracing::info!("Running on http://{listen_addr}:{port}");
@@ -199,3 +205,21 @@ async fn display_code_and_state(Query(params): Query<CallbackParams>) -> Html<St
Html(html)
}
// Handler for /.well-known/matrix/server
async fn well_known_matrix_server() -> (StatusCode, Json<Value>) {
let response = json!({
"m.server": "matrix.ppc.social:443"
});
(StatusCode::OK, Json(response))
}
// Handler for /.well-known/matrix/client
async fn well_known_matrix_client() -> (StatusCode, Json<Value>) {
let response = json!({
"m.homeserver": {
"base_url": "https://matrix.ppc.social:443"
}
});
(StatusCode::OK, Json(response))
}

View File

@@ -16,6 +16,13 @@ use crate::{
spacetime::SpacetimePart,
};
const MizeConfig = mconf!{
hi "t"
rustBinary "hello" ''
println!("hello world");
''
};
#[mize_part]
#[derive(Default)]
pub struct TimeTrack {