mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
assorted fixes
This commit is contained in:
@@ -30,34 +30,6 @@
|
|||||||
"nullable": []
|
"nullable": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"18aa5fba13df20495611fbbf7cb331f4b6da5b906148e0d9565905d3bb10071c": {
|
|
||||||
"query": "SELECT logged_out FROM session WHERE id = ?",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "logged_out",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Datetime"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
true
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"2932aa02735b6422fca4ba889abfb3de8598178d4690076dc278898753d9df62": {
|
|
||||||
"query": "UPDATE session SET logged_out = CURRENT_TIMESTAMP WHERE id = ?",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"3efd0daa61f4f8bead1adbe78a8225bc31fb940406d0415b578d3adc03a5e414": {
|
"3efd0daa61f4f8bead1adbe78a8225bc31fb940406d0415b578d3adc03a5e414": {
|
||||||
"query": "SELECT hash FROM password",
|
"query": "SELECT hash FROM password",
|
||||||
"describe": {
|
"describe": {
|
||||||
@@ -124,6 +96,16 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"63785dc5f193ea31e6f641a910c75857ccd288a3f6e9c4f704331531e4f0689f": {
|
||||||
|
"query": "UPDATE session SET last_active = CURRENT_TIMESTAMP WHERE id = ? AND logged_out IS NULL OR logged_out > CURRENT_TIMESTAMP",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
}
|
||||||
|
},
|
||||||
"6440354d73a67c041ea29508b43b5f309d45837a44f1a562051ad540d894c7d6": {
|
"6440354d73a67c041ea29508b43b5f309d45837a44f1a562051ad540d894c7d6": {
|
||||||
"query": "DELETE FROM ssh_keys WHERE fingerprint = ?",
|
"query": "DELETE FROM ssh_keys WHERE fingerprint = ?",
|
||||||
"describe": {
|
"describe": {
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use basic_cookies::Cookie;
|
use basic_cookies::Cookie;
|
||||||
use chrono::NaiveDateTime;
|
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use http::header::COOKIE;
|
use http::header::COOKIE;
|
||||||
use http::HeaderValue;
|
use http::HeaderValue;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use rpc_toolkit::command;
|
use rpc_toolkit::command;
|
||||||
use rpc_toolkit::command_helpers::prelude::{RequestParts, ResponseParts};
|
use rpc_toolkit::command_helpers::prelude::{RequestParts, ResponseParts};
|
||||||
|
use rpc_toolkit::yajrc::RpcError;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::context::EitherContext;
|
use crate::context::EitherContext;
|
||||||
use crate::middleware::auth::{get_id, hash_token};
|
use crate::middleware::auth::{get_id, hash_token};
|
||||||
use crate::util::{display_none, display_serializable, IoFormat};
|
use crate::util::{display_none, display_serializable, IoFormat};
|
||||||
use crate::{Error, ResultExt};
|
use crate::{ensure_code, Error, ResultExt};
|
||||||
|
|
||||||
#[command(subcommands(login, logout))]
|
#[command(subcommands(login, logout, session))]
|
||||||
pub fn auth(#[context] ctx: EitherContext) -> Result<EitherContext, Error> {
|
pub fn auth(#[context] ctx: EitherContext) -> Result<EitherContext, Error> {
|
||||||
Ok(ctx)
|
Ok(ctx)
|
||||||
}
|
}
|
||||||
@@ -58,12 +59,16 @@ pub async fn login(
|
|||||||
.fetch_one(&mut handle)
|
.fetch_one(&mut handle)
|
||||||
.await?
|
.await?
|
||||||
.hash;
|
.hash;
|
||||||
argon2::verify_encoded(&pw_hash, password.as_bytes()).map_err(|_| {
|
ensure_code!(
|
||||||
Error::new(
|
argon2::verify_encoded(&pw_hash, password.as_bytes()).map_err(|_| {
|
||||||
anyhow!("Password Incorrect"),
|
Error::new(
|
||||||
crate::ErrorKind::Authorization,
|
anyhow!("Password Incorrect"),
|
||||||
)
|
crate::ErrorKind::Authorization,
|
||||||
})?;
|
)
|
||||||
|
})?,
|
||||||
|
crate::ErrorKind::Authorization,
|
||||||
|
"Password Incorrect"
|
||||||
|
);
|
||||||
let token = base32::encode(
|
let token = base32::encode(
|
||||||
base32::Alphabet::RFC4648 { padding: false },
|
base32::Alphabet::RFC4648 { padding: false },
|
||||||
&rand::random::<[u8; 16]>(),
|
&rand::random::<[u8; 16]>(),
|
||||||
@@ -107,7 +112,7 @@ pub async fn logout(
|
|||||||
if let Some(session) = cookies.iter().find(|c| c.get_name() == "session") {
|
if let Some(session) = cookies.iter().find(|c| c.get_name() == "session") {
|
||||||
let token = session.get_value();
|
let token = session.get_value();
|
||||||
let id = hash_token(token);
|
let id = hash_token(token);
|
||||||
kill(ctx, id).await?;
|
kill(ctx, vec![id]).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -116,8 +121,8 @@ pub async fn logout(
|
|||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct Session {
|
pub struct Session {
|
||||||
logged_in: NaiveDateTime,
|
logged_in: DateTime<Utc>,
|
||||||
last_active: NaiveDateTime,
|
last_active: DateTime<Utc>,
|
||||||
user_agent: Option<String>,
|
user_agent: Option<String>,
|
||||||
metadata: Value,
|
metadata: Value,
|
||||||
}
|
}
|
||||||
@@ -187,8 +192,8 @@ pub async fn list(
|
|||||||
Ok((
|
Ok((
|
||||||
row.id,
|
row.id,
|
||||||
Session {
|
Session {
|
||||||
logged_in: row.logged_in,
|
logged_in: DateTime::from_utc(row.logged_in, Utc),
|
||||||
last_active: row.last_active,
|
last_active: DateTime::from_utc(row.last_active, Utc),
|
||||||
user_agent: row.user_agent,
|
user_agent: row.user_agent,
|
||||||
metadata: serde_json::from_str(&row.metadata)
|
metadata: serde_json::from_str(&row.metadata)
|
||||||
.with_kind(crate::ErrorKind::Database)?,
|
.with_kind(crate::ErrorKind::Database)?,
|
||||||
@@ -199,13 +204,20 @@ pub async fn list(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_comma_separated(arg: &str, _: &ArgMatches<'_>) -> Result<Vec<String>, RpcError> {
|
||||||
|
Ok(arg.split(",").map(|s| s.to_owned()).collect())
|
||||||
|
}
|
||||||
|
|
||||||
#[command(display(display_none))]
|
#[command(display(display_none))]
|
||||||
pub async fn kill(#[context] ctx: EitherContext, #[arg] id: String) -> Result<(), Error> {
|
pub async fn kill(
|
||||||
|
#[context] ctx: EitherContext,
|
||||||
|
#[arg(parse(parse_comma_separated))] ids: Vec<String>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let rpc_ctx = ctx.as_rpc().unwrap();
|
let rpc_ctx = ctx.as_rpc().unwrap();
|
||||||
sqlx::query!(
|
sqlx::query(&format!(
|
||||||
"UPDATE session SET logged_out = CURRENT_TIMESTAMP WHERE id = ?",
|
"UPDATE session SET logged_out = CURRENT_TIMESTAMP WHERE id IN ('{}')",
|
||||||
id
|
ids.join("','")
|
||||||
)
|
))
|
||||||
.execute(&mut rpc_ctx.secret_store.acquire().await?)
|
.execute(&mut rpc_ctx.secret_store.acquire().await?)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ fn inner_main() -> Result<(), Error> {
|
|||||||
|e: RpcError| {
|
|e: RpcError| {
|
||||||
match e.data {
|
match e.data {
|
||||||
Some(Value::String(s)) => eprintln!("{}: {}", e.message, s),
|
Some(Value::String(s)) => eprintln!("{}: {}", e.message, s),
|
||||||
Some(Value::Object(o)) => if let Some(Value::String(s)) = o.get("message") {
|
Some(Value::Object(o)) => if let Some(Value::String(s)) = o.get("details") {
|
||||||
eprintln!("{}: {}", e.message, s)
|
eprintln!("{}: {}", e.message, s)
|
||||||
}
|
}
|
||||||
Some(a) => eprintln!("{}: {}", e.message, a),
|
Some(a) => eprintln!("{}: {}", e.message, a),
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ fn inner_main() -> Result<(), Error> {
|
|||||||
|e: RpcError| {
|
|e: RpcError| {
|
||||||
match e.data {
|
match e.data {
|
||||||
Some(Value::String(s)) => eprintln!("{}: {}", e.message, s),
|
Some(Value::String(s)) => eprintln!("{}: {}", e.message, s),
|
||||||
Some(Value::Object(o)) => if let Some(Value::String(s)) = o.get("message") {
|
Some(Value::Object(o)) => if let Some(Value::String(s)) = o.get("details") {
|
||||||
eprintln!("{}: {}", e.message, s)
|
eprintln!("{}: {}", e.message, s)
|
||||||
}
|
}
|
||||||
Some(a) => eprintln!("{}: {}", e.message, a),
|
Some(a) => eprintln!("{}: {}", e.message, a),
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ use tokio_tungstenite::WebSocketStream;
|
|||||||
pub use self::model::DatabaseModel;
|
pub use self::model::DatabaseModel;
|
||||||
use self::util::WithRevision;
|
use self::util::WithRevision;
|
||||||
use crate::context::{EitherContext, RpcContext};
|
use crate::context::{EitherContext, RpcContext};
|
||||||
|
use crate::middleware::auth::is_authed;
|
||||||
use crate::util::{display_serializable, IoFormat};
|
use crate::util::{display_serializable, IoFormat};
|
||||||
use crate::{Error, ResultExt};
|
use crate::{Error, ResultExt};
|
||||||
|
|
||||||
@@ -55,6 +56,9 @@ async fn ws_handler<
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn subscribe(ctx: RpcContext, req: Request<Body>) -> Result<Response<Body>, Error> {
|
pub async fn subscribe(ctx: RpcContext, req: Request<Body>) -> Result<Response<Body>, Error> {
|
||||||
|
let (parts, body) = req.into_parts();
|
||||||
|
// is_authed(&ctx, &parts).await?;
|
||||||
|
let req = Request::from_parts(parts, body);
|
||||||
let (res, ws_fut) = hyper_ws_listener::create_ws(req).with_kind(crate::ErrorKind::Network)?;
|
let (res, ws_fut) = hyper_ws_listener::create_ws(req).with_kind(crate::ErrorKind::Network)?;
|
||||||
if let Some(ws_fut) = ws_fut {
|
if let Some(ws_fut) = ws_fut {
|
||||||
tokio::task::spawn(async move {
|
tokio::task::spawn(async move {
|
||||||
|
|||||||
@@ -204,6 +204,8 @@ pub struct InstalledPackageDataEntry {
|
|||||||
pub manifest: Manifest,
|
pub manifest: Manifest,
|
||||||
pub system_pointers: Vec<SystemPointerSpec>,
|
pub system_pointers: Vec<SystemPointerSpec>,
|
||||||
#[model]
|
#[model]
|
||||||
|
pub dependency_info: IndexMap<PackageId, StaticDependencyInfo>,
|
||||||
|
#[model]
|
||||||
pub current_dependents: IndexMap<PackageId, CurrentDependencyInfo>,
|
pub current_dependents: IndexMap<PackageId, CurrentDependencyInfo>,
|
||||||
#[model]
|
#[model]
|
||||||
pub current_dependencies: IndexMap<PackageId, CurrentDependencyInfo>,
|
pub current_dependencies: IndexMap<PackageId, CurrentDependencyInfo>,
|
||||||
@@ -211,6 +213,13 @@ pub struct InstalledPackageDataEntry {
|
|||||||
pub interface_addresses: InterfaceAddressMap,
|
pub interface_addresses: InterfaceAddressMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
pub struct StaticDependencyInfo {
|
||||||
|
pub manifest: Option<Manifest>,
|
||||||
|
pub icon: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel)]
|
#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct CurrentDependencyInfo {
|
pub struct CurrentDependencyInfo {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use std::time::Duration;
|
|||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use emver::VersionRange;
|
use emver::VersionRange;
|
||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
use http::HeaderMap;
|
use http::{HeaderMap, StatusCode};
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::{IndexMap, IndexSet};
|
||||||
use patch_db::json_ptr::JsonPointer;
|
use patch_db::json_ptr::JsonPointer;
|
||||||
use patch_db::{
|
use patch_db::{
|
||||||
@@ -28,7 +28,8 @@ use tokio::io::{AsyncRead, AsyncSeek, AsyncSeekExt, AsyncWrite, AsyncWriteExt};
|
|||||||
use self::progress::{InstallProgress, InstallProgressTracker};
|
use self::progress::{InstallProgress, InstallProgressTracker};
|
||||||
use crate::context::{EitherContext, ExtendedContext, RpcContext};
|
use crate::context::{EitherContext, ExtendedContext, RpcContext};
|
||||||
use crate::db::model::{
|
use crate::db::model::{
|
||||||
CurrentDependencyInfo, InstalledPackageDataEntry, PackageDataEntry, StaticFiles,
|
CurrentDependencyInfo, InstalledPackageDataEntry, PackageDataEntry, StaticDependencyInfo,
|
||||||
|
StaticFiles,
|
||||||
};
|
};
|
||||||
use crate::s9pk::manifest::{Manifest, PackageId};
|
use crate::s9pk::manifest::{Manifest, PackageId};
|
||||||
use crate::s9pk::reader::S9pkReader;
|
use crate::s9pk::reader::S9pkReader;
|
||||||
@@ -272,6 +273,76 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
|
|||||||
.await?;
|
.await?;
|
||||||
log::info!("Install {}@{}: Unpacked Manifest", pkg_id, version);
|
log::info!("Install {}@{}: Unpacked Manifest", pkg_id, version);
|
||||||
|
|
||||||
|
log::info!("Install {}@{}: Fetching Dependency Info", pkg_id, version);
|
||||||
|
let mut dependency_info = IndexMap::with_capacity(manifest.dependencies.0.len());
|
||||||
|
let reg_url = ctx.package_registry_url().await?;
|
||||||
|
for (dep, info) in &manifest.dependencies.0 {
|
||||||
|
let manifest: Option<Manifest> = match reqwest::get(format!(
|
||||||
|
"{}/package/manifest/{}?version={}",
|
||||||
|
reg_url, dep, info.version
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
.with_kind(crate::ErrorKind::Registry)?
|
||||||
|
.error_for_status()
|
||||||
|
{
|
||||||
|
Ok(a) => Ok(Some(
|
||||||
|
a.json()
|
||||||
|
.await
|
||||||
|
.with_kind(crate::ErrorKind::Deserialization)?,
|
||||||
|
)),
|
||||||
|
Err(e) if e.status() == Some(StatusCode::BAD_REQUEST) => Ok(None),
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
.with_kind(crate::ErrorKind::Registry)?;
|
||||||
|
if let Some(manifest) = manifest {
|
||||||
|
let dir = Path::new(PKG_PUBLIC_DIR)
|
||||||
|
.join(&manifest.id)
|
||||||
|
.join(manifest.version.as_str());
|
||||||
|
let icon_path = dir.join(format!("icon.{}", manifest.assets.icon_type()));
|
||||||
|
if tokio::fs::metadata(&icon_path).await.is_err() {
|
||||||
|
tokio::fs::create_dir_all(&dir).await?;
|
||||||
|
let icon = reqwest::get(format!(
|
||||||
|
"{}/package/icon/{}?version={}",
|
||||||
|
reg_url, dep, info.version
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
.with_kind(crate::ErrorKind::Registry)?;
|
||||||
|
let mut dst = File::create(&icon_path).await?;
|
||||||
|
tokio::io::copy(
|
||||||
|
&mut tokio_util::io::StreamReader::new(icon.bytes_stream().map_err(|e| {
|
||||||
|
std::io::Error::new(
|
||||||
|
if e.is_connect() {
|
||||||
|
std::io::ErrorKind::ConnectionRefused
|
||||||
|
} else if e.is_timeout() {
|
||||||
|
std::io::ErrorKind::TimedOut
|
||||||
|
} else {
|
||||||
|
std::io::ErrorKind::Other
|
||||||
|
},
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
})),
|
||||||
|
&mut dst,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
dst.sync_all().await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
dependency_info.insert(
|
||||||
|
dep.clone(),
|
||||||
|
StaticDependencyInfo {
|
||||||
|
icon: format!(
|
||||||
|
"/public/package-data/{}/{}/icon.{}",
|
||||||
|
manifest.id,
|
||||||
|
manifest.version,
|
||||||
|
manifest.assets.icon_type()
|
||||||
|
),
|
||||||
|
manifest: Some(manifest),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log::info!("Install {}@{}: Fetched Dependency Info", pkg_id, version);
|
||||||
|
|
||||||
let public_dir_path = Path::new(PKG_PUBLIC_DIR)
|
let public_dir_path = Path::new(PKG_PUBLIC_DIR)
|
||||||
.join(pkg_id)
|
.join(pkg_id)
|
||||||
.join(version.as_str());
|
.join(version.as_str());
|
||||||
@@ -408,6 +479,7 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
|
|||||||
},
|
},
|
||||||
manifest: manifest.clone(),
|
manifest: manifest.clone(),
|
||||||
system_pointers: Vec::new(),
|
system_pointers: Vec::new(),
|
||||||
|
dependency_info,
|
||||||
current_dependents: {
|
current_dependents: {
|
||||||
// search required dependencies
|
// search required dependencies
|
||||||
let mut deps = IndexMap::new();
|
let mut deps = IndexMap::new();
|
||||||
|
|||||||
@@ -47,18 +47,18 @@ pub fn hash_token(token: &str) -> String {
|
|||||||
.to_lowercase()
|
.to_lowercase()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn is_authed(ctx: &RpcContext, req: &RequestParts) -> Result<(), Error> {
|
pub async fn is_authed(ctx: &RpcContext, req: &RequestParts) -> Result<(), Error> {
|
||||||
let id = get_id(req)?;
|
let id = get_id(req)?;
|
||||||
let exp = sqlx::query!("SELECT logged_out FROM session WHERE id = ?", id)
|
let session = sqlx::query!("UPDATE session SET last_active = CURRENT_TIMESTAMP WHERE id = ? AND logged_out IS NULL OR logged_out > CURRENT_TIMESTAMP", id)
|
||||||
.fetch_one(&mut ctx.secret_store.acquire().await?)
|
.execute(&mut ctx.secret_store.acquire().await?)
|
||||||
.await?;
|
.await?;
|
||||||
match exp.logged_out {
|
if session.rows_affected() == 0 {
|
||||||
Some(exp) if exp >= Utc::now().naive_utc() => Err(Error::new(
|
return Err(Error::new(
|
||||||
anyhow!("UNAUTHORIZED"),
|
anyhow!("UNAUTHORIZED"),
|
||||||
crate::ErrorKind::Authorization,
|
crate::ErrorKind::Authorization,
|
||||||
)),
|
));
|
||||||
_ => Ok(()),
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn auth<M: Metadata>(ctx: RpcContext) -> DynMiddleware<M> {
|
pub fn auth<M: Metadata>(ctx: RpcContext) -> DynMiddleware<M> {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export class SessionsPage {
|
|||||||
|
|
||||||
async ngOnInit () {
|
async ngOnInit () {
|
||||||
try {
|
try {
|
||||||
this.sessionInfo = await this.embassyApi.getSessions({ })
|
this.sessionInfo = await this.embassyApi.getSessions({})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.errToast.present(e.message)
|
this.errToast.present(e.message)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export module RR {
|
|||||||
export type LoginReq = { password: string, metadata: SessionMetadata } // auth.login - unauthed
|
export type LoginReq = { password: string, metadata: SessionMetadata } // auth.login - unauthed
|
||||||
export type loginRes = null
|
export type loginRes = null
|
||||||
|
|
||||||
export type LogoutReq = { } // auth.logout
|
export type LogoutReq = {} // auth.logout
|
||||||
export type LogoutRes = null
|
export type LogoutRes = null
|
||||||
|
|
||||||
// server
|
// server
|
||||||
@@ -30,26 +30,26 @@ export module RR {
|
|||||||
export type GetServerLogsReq = { before?: string } // server.logs
|
export type GetServerLogsReq = { before?: string } // server.logs
|
||||||
export type GetServerLogsRes = Log[]
|
export type GetServerLogsRes = Log[]
|
||||||
|
|
||||||
export type GetServerMetricsReq = { } // server.metrics
|
export type GetServerMetricsReq = {} // server.metrics
|
||||||
export type GetServerMetricsRes = Metrics
|
export type GetServerMetricsRes = Metrics
|
||||||
|
|
||||||
export type UpdateServerReq = WithExpire<{ }> // server.update
|
export type UpdateServerReq = WithExpire<{}> // server.update
|
||||||
export type UpdateServerRes = WithRevision<null>
|
export type UpdateServerRes = WithRevision<null>
|
||||||
|
|
||||||
export type RestartServerReq = { } // server.restart
|
export type RestartServerReq = {} // server.restart
|
||||||
export type RestartServerRes = null
|
export type RestartServerRes = null
|
||||||
|
|
||||||
export type ShutdownServerReq = { } // server.shutdown
|
export type ShutdownServerReq = {} // server.shutdown
|
||||||
export type ShutdownServerRes = null
|
export type ShutdownServerRes = null
|
||||||
|
|
||||||
// network
|
// network
|
||||||
|
|
||||||
export type RefreshLanReq = { } // network.lan.refresh
|
export type RefreshLanReq = {} // network.lan.refresh
|
||||||
export type RefreshLanRes = null
|
export type RefreshLanRes = null
|
||||||
|
|
||||||
// sessions
|
// sessions
|
||||||
|
|
||||||
export type GetSessionsReq = { } // sessions.list
|
export type GetSessionsReq = {} // sessions.list
|
||||||
export type GetSessionsRes = {
|
export type GetSessionsRes = {
|
||||||
current: string,
|
current: string,
|
||||||
sessions: { [hash: string]: Session }
|
sessions: { [hash: string]: Session }
|
||||||
@@ -78,7 +78,7 @@ export module RR {
|
|||||||
export type DeleteNotificationReq = { id: string } // notification.delete
|
export type DeleteNotificationReq = { id: string } // notification.delete
|
||||||
export type DeleteNotificationRes = null
|
export type DeleteNotificationRes = null
|
||||||
|
|
||||||
export type DeleteAllNotificationsReq = { } // notification.delete.all
|
export type DeleteAllNotificationsReq = {} // notification.delete.all
|
||||||
export type DeleteAllNotificationsRes = null
|
export type DeleteAllNotificationsRes = null
|
||||||
|
|
||||||
// wifi
|
// wifi
|
||||||
@@ -100,7 +100,7 @@ export module RR {
|
|||||||
|
|
||||||
// ssh
|
// ssh
|
||||||
|
|
||||||
export type GetSSHKeysReq = { } // ssh.get
|
export type GetSSHKeysReq = {} // ssh.get
|
||||||
export type GetSSHKeysRes = SSHKeys
|
export type GetSSHKeysRes = SSHKeys
|
||||||
|
|
||||||
export type AddSSHKeyReq = { pubkey: string } // ssh.add
|
export type AddSSHKeyReq = { pubkey: string } // ssh.add
|
||||||
@@ -119,7 +119,7 @@ export module RR {
|
|||||||
|
|
||||||
// disk
|
// disk
|
||||||
|
|
||||||
export type GetDisksReq = { } // disk.list
|
export type GetDisksReq = {} // disk.list
|
||||||
export type GetDisksRes = DiskInfo
|
export type GetDisksRes = DiskInfo
|
||||||
|
|
||||||
export type EjectDisksReq = { logicalname: string } // disk.eject
|
export type EjectDisksReq = { logicalname: string } // disk.eject
|
||||||
@@ -178,10 +178,10 @@ export module RR {
|
|||||||
|
|
||||||
// marketplace
|
// marketplace
|
||||||
|
|
||||||
export type GetMarketplaceDataReq = { }
|
export type GetMarketplaceDataReq = {}
|
||||||
export type GetMarketplaceDataRes = MarketplaceData
|
export type GetMarketplaceDataRes = MarketplaceData
|
||||||
|
|
||||||
export type GetMarketplaceEOSReq = { }
|
export type GetMarketplaceEOSReq = {}
|
||||||
export type GetMarketplaceEOSRes = MarketplaceEOS
|
export type GetMarketplaceEOSRes = MarketplaceEOS
|
||||||
|
|
||||||
export type GetMarketplacePackagesReq = {
|
export type GetMarketplacePackagesReq = {
|
||||||
@@ -195,10 +195,10 @@ export module RR {
|
|||||||
export type GetMarketplacePackagesRes = MarketplacePkg[]
|
export type GetMarketplacePackagesRes = MarketplacePkg[]
|
||||||
|
|
||||||
export type GetReleaseNotesReq = { id: string }
|
export type GetReleaseNotesReq = { id: string }
|
||||||
export type GetReleaseNotesRes = { [version: string]: string}
|
export type GetReleaseNotesRes = { [version: string]: string }
|
||||||
|
|
||||||
export type GetLatestVersionReq = { ids: string[] }
|
export type GetLatestVersionReq = { ids: string[] }
|
||||||
export type GetLatestVersionRes = { [id: string]: string}
|
export type GetLatestVersionRes = { [id: string]: string }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,8 +334,8 @@ export enum NotificationLevel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type NotificationData<T> = T extends 0 ? null :
|
export type NotificationData<T> = T extends 0 ? null :
|
||||||
T extends 1 ? BackupReport :
|
T extends 1 ? BackupReport :
|
||||||
any
|
any
|
||||||
|
|
||||||
export interface BackupReport {
|
export interface BackupReport {
|
||||||
server: {
|
server: {
|
||||||
|
|||||||
Reference in New Issue
Block a user