mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
ephemeral logins
This commit is contained in:
@@ -185,6 +185,8 @@ pub struct LoginParams {
|
||||
#[serde(rename = "__auth_userAgent")] // from Auth middleware
|
||||
user_agent: Option<String>,
|
||||
#[serde(default)]
|
||||
ephemeral: bool,
|
||||
#[serde(default)]
|
||||
#[ts(type = "any")]
|
||||
metadata: Value,
|
||||
}
|
||||
@@ -195,28 +197,46 @@ pub async fn login_impl(
|
||||
LoginParams {
|
||||
password,
|
||||
user_agent,
|
||||
ephemeral,
|
||||
metadata,
|
||||
}: LoginParams,
|
||||
) -> Result<LoginRes, Error> {
|
||||
let password = password.unwrap_or_default().decrypt(&ctx)?;
|
||||
|
||||
ctx.db
|
||||
.mutate(|db| {
|
||||
check_password_against_db(db, &password)?;
|
||||
let hash_token = HashSessionToken::new();
|
||||
db.as_private_mut().as_sessions_mut().insert(
|
||||
hash_token.hashed(),
|
||||
&Session {
|
||||
if ephemeral {
|
||||
check_password_against_db(&ctx.db.peek().await, &password)?;
|
||||
let hash_token = HashSessionToken::new();
|
||||
ctx.ephemeral_sessions.mutate(|s| {
|
||||
s.0.insert(
|
||||
hash_token.hashed().clone(),
|
||||
Session {
|
||||
logged_in: Utc::now(),
|
||||
last_active: Utc::now(),
|
||||
user_agent,
|
||||
metadata,
|
||||
},
|
||||
)?;
|
||||
)
|
||||
});
|
||||
Ok(hash_token.to_login_res())
|
||||
} else {
|
||||
ctx.db
|
||||
.mutate(|db| {
|
||||
check_password_against_db(db, &password)?;
|
||||
let hash_token = HashSessionToken::new();
|
||||
db.as_private_mut().as_sessions_mut().insert(
|
||||
hash_token.hashed(),
|
||||
&Session {
|
||||
logged_in: Utc::now(),
|
||||
last_active: Utc::now(),
|
||||
user_agent,
|
||||
metadata,
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(hash_token.to_login_res())
|
||||
})
|
||||
.await
|
||||
Ok(hash_token.to_login_res())
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Parser, TS)]
|
||||
@@ -329,9 +349,15 @@ pub async fn list(
|
||||
ctx: RpcContext,
|
||||
ListParams { session, .. }: ListParams,
|
||||
) -> Result<SessionList, Error> {
|
||||
let mut sessions = ctx.db.peek().await.into_private().into_sessions().de()?;
|
||||
ctx.ephemeral_sessions.mutate(|s| {
|
||||
sessions
|
||||
.0
|
||||
.extend(s.0.iter().map(|(k, v)| (k.clone(), v.clone())))
|
||||
});
|
||||
Ok(SessionList {
|
||||
current: HashSessionToken::from_token(session).hashed().clone(),
|
||||
sessions: ctx.db.peek().await.into_private().into_sessions().de()?,
|
||||
sessions,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ use tracing::instrument;
|
||||
|
||||
use super::setup::CURRENT_SECRET;
|
||||
use crate::account::AccountInfo;
|
||||
use crate::auth::Sessions;
|
||||
use crate::context::config::ServerConfig;
|
||||
use crate::db::model::Database;
|
||||
use crate::dependencies::compute_dependency_config_errs;
|
||||
@@ -34,6 +35,7 @@ use crate::service::ServiceMap;
|
||||
use crate::shutdown::Shutdown;
|
||||
use crate::system::get_mem_info;
|
||||
use crate::util::lshw::{lshw, LshwDevice};
|
||||
use crate::util::sync::SyncMutex;
|
||||
|
||||
pub struct RpcContextSeed {
|
||||
is_closed: AtomicBool,
|
||||
@@ -42,6 +44,7 @@ pub struct RpcContextSeed {
|
||||
pub ethernet_interface: String,
|
||||
pub datadir: PathBuf,
|
||||
pub disk_guid: Arc<String>,
|
||||
pub ephemeral_sessions: SyncMutex<Sessions>,
|
||||
pub db: TypedPatchDb<Database>,
|
||||
pub sync_db: watch::Sender<u64>,
|
||||
pub account: RwLock<AccountInfo>,
|
||||
@@ -213,6 +216,7 @@ impl RpcContext {
|
||||
find_eth_iface().await?
|
||||
},
|
||||
disk_guid,
|
||||
ephemeral_sessions: SyncMutex::new(Sessions::new()),
|
||||
sync_db: watch::Sender::new(db.sequence().await),
|
||||
db,
|
||||
account: RwLock::new(account),
|
||||
|
||||
@@ -51,6 +51,11 @@ impl HasLoggedOutSessions {
|
||||
for sid in &to_log_out {
|
||||
ctx.open_authed_continuations.kill(sid)
|
||||
}
|
||||
ctx.ephemeral_sessions.mutate(|s| {
|
||||
for sid in &to_log_out {
|
||||
s.0.remove(sid);
|
||||
}
|
||||
});
|
||||
ctx.db
|
||||
.mutate(|db| {
|
||||
let sessions = db.as_private_mut().as_sessions_mut();
|
||||
@@ -110,20 +115,29 @@ impl HasValidSession {
|
||||
ctx: &RpcContext,
|
||||
) -> Result<Self, Error> {
|
||||
let session_hash = session_token.hashed();
|
||||
ctx.db
|
||||
.mutate(|db| {
|
||||
db.as_private_mut()
|
||||
.as_sessions_mut()
|
||||
.as_idx_mut(session_hash)
|
||||
.ok_or_else(|| {
|
||||
Error::new(eyre!("UNAUTHORIZED"), crate::ErrorKind::Authorization)
|
||||
})?
|
||||
.mutate(|s| {
|
||||
s.last_active = Utc::now();
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
.await?;
|
||||
if !ctx.ephemeral_sessions.mutate(|s| {
|
||||
if let Some(session) = s.0.get_mut(session_hash) {
|
||||
session.last_active = Utc::now();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}) {
|
||||
ctx.db
|
||||
.mutate(|db| {
|
||||
db.as_private_mut()
|
||||
.as_sessions_mut()
|
||||
.as_idx_mut(session_hash)
|
||||
.ok_or_else(|| {
|
||||
Error::new(eyre!("UNAUTHORIZED"), crate::ErrorKind::Authorization)
|
||||
})?
|
||||
.mutate(|s| {
|
||||
s.last_active = Utc::now();
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
.await?;
|
||||
}
|
||||
Ok(Self(SessionType::Session(session_token)))
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ pub mod net;
|
||||
pub mod rpc;
|
||||
pub mod rpc_client;
|
||||
pub mod serde;
|
||||
pub mod sync;
|
||||
|
||||
#[derive(Clone, Copy, Debug, ::serde::Deserialize, ::serde::Serialize)]
|
||||
pub enum Never {}
|
||||
|
||||
9
core/startos/src/util/sync.rs
Normal file
9
core/startos/src/util/sync.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
pub struct SyncMutex<T>(std::sync::Mutex<T>);
|
||||
impl<T> SyncMutex<T> {
|
||||
pub fn new(t: T) -> Self {
|
||||
Self(std::sync::Mutex::new(t))
|
||||
}
|
||||
pub fn mutate<F: FnOnce(&mut T) -> U, U>(&self, f: F) -> U {
|
||||
f(&mut *self.0.lock().unwrap())
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { PasswordType } from "./PasswordType"
|
||||
|
||||
export type LoginParams = { password: PasswordType | null; metadata: any }
|
||||
export type LoginParams = {
|
||||
password: PasswordType | null
|
||||
ephemeral: boolean
|
||||
metadata: any
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ export class LoginPage {
|
||||
await this.api.login({
|
||||
password: this.password,
|
||||
metadata: { platforms: getPlatforms() },
|
||||
ephemeral: window.location.host === 'localhost',
|
||||
})
|
||||
|
||||
this.password = ''
|
||||
|
||||
@@ -33,6 +33,7 @@ export module RR {
|
||||
export type LoginReq = {
|
||||
password: string
|
||||
metadata: SessionMetadata
|
||||
ephemeral?: boolean
|
||||
} // auth.login - unauthed
|
||||
export type loginRes = null
|
||||
|
||||
|
||||
@@ -73,8 +73,6 @@ export class ConfigService {
|
||||
const hostnameInfo =
|
||||
hosts[ui.addressInfo.hostId]?.hostnameInfo[ui.addressInfo.internalPort]
|
||||
|
||||
console.debug(hostnameInfo)
|
||||
|
||||
if (!hostnameInfo) return ''
|
||||
|
||||
const addressInfo = ui.addressInfo
|
||||
|
||||
Reference in New Issue
Block a user