steid

@jamesgill /

steid/src/main.rs
2.3 KBCode·Blame·Raw
14223e7feat: claim, sign in, and sign out through the browser1mo
1use steid::{
2 application::{AppConfig, is_claimed},
3 domain::SetupToken,
264c436fix: session cookie survives plain-HTTP localhost in dev1mo
4 infrastructure::{
5 self,
6 repository::SqliteUserRepo,
7 web::{context::SetupState, session_cookie::InsecureCookieTokenStore},
8 },
14223e7feat: claim, sign in, and sign out through the browser1mo
9};
10use topcoat::{
11 cookie::RouterBuilderCookieExt,
12 router::{Router, RouterBuilderDiscoverExt},
13 session::{RouterBuilderSessionExt, SessionConfig},
14};
e6f4874feat: topcoat skeleton serving a page1mo
15
16#[tokio::main]
0d12f7dfeat: config from env and SQLite pool in app context1mo
17async fn main() -> Result<(), Box<dyn std::error::Error>> {
18 dotenvy::dotenv().ok();
e6f4874feat: topcoat skeleton serving a page1mo
19
0d12f7dfeat: config from env and SQLite pool in app context1mo
20 let config = AppConfig::from_env()?;
21 let pool = infrastructure::database::connect(&config.database_url).await?;
22
14223e7feat: claim, sign in, and sign out through the browser1mo
23 let mut builder = Router::builder()
24 .cookies()
264c436fix: session cookie survives plain-HTTP localhost in dev1mo
25 .sessions(session_config(config.insecure_cookies))
0d12f7dfeat: config from env and SQLite pool in app context1mo
26 .discover()
27 .app_context(config)
14223e7feat: claim, sign in, and sign out through the browser1mo
28 .app_context(pool.clone());
0d12f7dfeat: config from env and SQLite pool in app context1mo
29
14223e7feat: claim, sign in, and sign out through the browser1mo
30 // The setup token exists only while the instance is unclaimed, so a claimed
31 // installation has no token in context for a claim attempt to match against.
32 if !is_claimed(&SqliteUserRepo::new(pool)).await? {
33 let token = SetupToken::generate();
34 announce_setup(&token);
35 builder = builder.app_context(SetupState(token));
36 }
37
38 topcoat::start(builder.build()).await?;
e6f4874feat: topcoat skeleton serving a page1mo
39
0d12f7dfeat: config from env and SQLite pool in app context1mo
40 Ok(())
1111df1feat: init1mo
41}
14223e7feat: claim, sign in, and sign out through the browser1mo
42
264c436fix: session cookie survives plain-HTTP localhost in dev1mo
43/// Builds the session configuration.
44///
45/// The hardened default requires a trustworthy origin for its `Secure` cookie;
46/// browsers disagree about whether plain-HTTP localhost qualifies, and where it
47/// doesn't the cookie is dropped silently and every page renders signed out.
48fn session_config(insecure_cookies: bool) -> SessionConfig {
49 if insecure_cookies {
50 eprintln!();
51 eprintln!(" !! STEID_INSECURE_COOKIES is on: the session cookie has no Secure");
52 eprintln!(" !! flag and travels unencrypted. Local development only.");
53 eprintln!();
54
55 SessionConfig::builder()
56 .token_store(InsecureCookieTokenStore::new())
57 .build()
58 } else {
59 SessionConfig::default()
60 }
61}
62
14223e7feat: claim, sign in, and sign out through the browser1mo
63/// Prints the claim instructions. The only time the token is ever revealed.
64fn announce_setup(token: &SetupToken) {
65 println!();
66 println!(" This steid has no owner yet. Claim it at /setup with:");
67 println!();
68 println!(" {}", token.reveal());
69 println!();
70 println!(" The token is held in memory only — restarting issues a new one.");
71 println!();
72}