mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-02 05:23:14 +00:00
Merge branch 'next/minor' of github.com:Start9Labs/start-os into next/major
This commit is contained in:
@@ -7,7 +7,7 @@ use futures::future::BoxFuture;
|
||||
use futures::{Future, FutureExt};
|
||||
use imbl::Vector;
|
||||
use imbl_value::{to_value, InternedString};
|
||||
use patch_db::json_ptr::{JsonPointer, ROOT};
|
||||
use patch_db::json_ptr::ROOT;
|
||||
|
||||
use crate::context::RpcContext;
|
||||
use crate::db::model::Database;
|
||||
@@ -29,7 +29,12 @@ mod v0_3_6_alpha_7;
|
||||
mod v0_3_6_alpha_8;
|
||||
mod v0_3_6_alpha_9;
|
||||
|
||||
pub type Current = v0_3_6_alpha_9::Version; // VERSION_BUMP
|
||||
mod v0_3_6_alpha_10;
|
||||
mod v0_3_6_alpha_11;
|
||||
mod v0_3_6_alpha_12;
|
||||
mod v0_3_6_alpha_13;
|
||||
|
||||
pub type Current = v0_3_6_alpha_13::Version; // VERSION_BUMP
|
||||
|
||||
impl Current {
|
||||
#[instrument(skip(self, db))]
|
||||
@@ -52,7 +57,7 @@ impl Current {
|
||||
let pre_ups = PreUps::load(&from, &self).await?;
|
||||
db.apply_function(|mut db| {
|
||||
migrate_from_unchecked(&from, &self, pre_ups, &mut db)?;
|
||||
Ok::<_, Error>((db, ()))
|
||||
Ok::<_, Error>((to_value(&from_value::<Database>(db.clone())?)?, ()))
|
||||
})
|
||||
.await?;
|
||||
}
|
||||
@@ -62,31 +67,44 @@ impl Current {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn post_init(ctx: &RpcContext) -> Result<(), Error> {
|
||||
let mut peek;
|
||||
while let Some(version) = {
|
||||
peek = ctx.db.peek().await;
|
||||
peek.as_public()
|
||||
.as_server_info()
|
||||
.as_post_init_migration_todos()
|
||||
.de()?
|
||||
.first()
|
||||
.cloned()
|
||||
.map(Version::from_exver_version)
|
||||
.as_ref()
|
||||
.map(Version::as_version_t)
|
||||
.transpose()?
|
||||
} {
|
||||
version.0.post_up(ctx).await?;
|
||||
ctx.db
|
||||
.mutate(|db| {
|
||||
db.as_public_mut()
|
||||
.as_server_info_mut()
|
||||
.as_post_init_migration_todos_mut()
|
||||
.mutate(|m| Ok(m.remove(&version.0.semver())))
|
||||
})
|
||||
.await?;
|
||||
pub async fn post_init(
|
||||
ctx: &RpcContext,
|
||||
mut progress: PhaseProgressTrackerHandle,
|
||||
) -> Result<(), Error> {
|
||||
let mut peek = ctx.db.peek().await;
|
||||
let todos = peek
|
||||
.as_public()
|
||||
.as_server_info()
|
||||
.as_post_init_migration_todos()
|
||||
.de()?;
|
||||
if !todos.is_empty() {
|
||||
progress.set_total(todos.len() as u64);
|
||||
while let Some(version) = {
|
||||
peek = ctx.db.peek().await;
|
||||
peek.as_public()
|
||||
.as_server_info()
|
||||
.as_post_init_migration_todos()
|
||||
.de()?
|
||||
.first()
|
||||
.cloned()
|
||||
.map(Version::from_exver_version)
|
||||
.as_ref()
|
||||
.map(Version::as_version_t)
|
||||
.transpose()?
|
||||
} {
|
||||
version.0.post_up(ctx).await?;
|
||||
ctx.db
|
||||
.mutate(|db| {
|
||||
db.as_public_mut()
|
||||
.as_server_info_mut()
|
||||
.as_post_init_migration_todos_mut()
|
||||
.mutate(|m| Ok(m.remove(&version.0.semver())))
|
||||
})
|
||||
.await?;
|
||||
progress += 1;
|
||||
}
|
||||
}
|
||||
progress.complete();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -108,6 +126,10 @@ enum Version {
|
||||
V0_3_6_alpha_7(Wrapper<v0_3_6_alpha_7::Version>),
|
||||
V0_3_6_alpha_8(Wrapper<v0_3_6_alpha_8::Version>),
|
||||
V0_3_6_alpha_9(Wrapper<v0_3_6_alpha_9::Version>),
|
||||
V0_3_6_alpha_10(Wrapper<v0_3_6_alpha_10::Version>),
|
||||
V0_3_6_alpha_11(Wrapper<v0_3_6_alpha_11::Version>),
|
||||
V0_3_6_alpha_12(Wrapper<v0_3_6_alpha_12::Version>),
|
||||
V0_3_6_alpha_13(Wrapper<v0_3_6_alpha_13::Version>), // VERSION_BUMP
|
||||
Other(exver::Version),
|
||||
}
|
||||
|
||||
@@ -141,6 +163,10 @@ impl Version {
|
||||
Self::V0_3_6_alpha_7(v) => DynVersion(Box::new(v.0)),
|
||||
Self::V0_3_6_alpha_8(v) => DynVersion(Box::new(v.0)),
|
||||
Self::V0_3_6_alpha_9(v) => DynVersion(Box::new(v.0)),
|
||||
Self::V0_3_6_alpha_10(v) => DynVersion(Box::new(v.0)),
|
||||
Self::V0_3_6_alpha_11(v) => DynVersion(Box::new(v.0)),
|
||||
Self::V0_3_6_alpha_12(v) => DynVersion(Box::new(v.0)),
|
||||
Self::V0_3_6_alpha_13(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP
|
||||
Self::Other(v) => {
|
||||
return Err(Error::new(
|
||||
eyre!("unknown version {v}"),
|
||||
@@ -166,6 +192,10 @@ impl Version {
|
||||
Version::V0_3_6_alpha_7(Wrapper(x)) => x.semver(),
|
||||
Version::V0_3_6_alpha_8(Wrapper(x)) => x.semver(),
|
||||
Version::V0_3_6_alpha_9(Wrapper(x)) => x.semver(),
|
||||
Version::V0_3_6_alpha_10(Wrapper(x)) => x.semver(),
|
||||
Version::V0_3_6_alpha_11(Wrapper(x)) => x.semver(),
|
||||
Version::V0_3_6_alpha_12(Wrapper(x)) => x.semver(),
|
||||
Version::V0_3_6_alpha_13(Wrapper(x)) => x.semver(), // VERSION_BUMP
|
||||
Version::Other(x) => x.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,17 +17,16 @@ StartOS v0.3.6 is a complete rewrite of the OS internals (everything you don't s
|
||||
## Changelog
|
||||
|
||||
- [Switch to lxc-based container runtime](#lxc)
|
||||
- [Update s9pk archive format](#new-s9pk-archive-format)
|
||||
- [Improve config](#better-config)
|
||||
- [Unify Actions](#unify-actions)
|
||||
- [Update s9pk archive format](#s9pk-archive-format)
|
||||
- [Improve Actions](#actions)
|
||||
- [Use squashfs images for OS updates](#squashfs-updates)
|
||||
- [Introduce Typescript package API and SDK](#typescript-package-api-and-sdk)
|
||||
- [Introduce Typescript package API and SDK](#typescript-sdk)
|
||||
- [Remove Postgresql](#remove-postgressql)
|
||||
- [Implement detailed progress reporting](#progress-reporting)
|
||||
- [Improve registry protocol](#registry-protocol)
|
||||
- [Replace unique .local URLs with unique ports](#lan-port-forwarding)
|
||||
- [Use start-fs Fuse module for improved backups](#improved-backups)
|
||||
- [Switch to Exver for versioning](#Exver)
|
||||
- [Switch to Exver for versioning](#exver)
|
||||
- [Support clearnet hosting via start-cli](#clearnet)
|
||||
|
||||
### LXC
|
||||
@@ -38,21 +37,17 @@ StartOS now uses a nested container paradigm based on LXC for the outer containe
|
||||
|
||||
The S9PK archive format has been overhauled to allow for signature verification of partial downloads, and allow direct mounting of container images without unpacking the s9pk.
|
||||
|
||||
### Better config
|
||||
|
||||
Expanded support for input types and a new UI makes configuring services easier and more powerful.
|
||||
|
||||
### Actions
|
||||
|
||||
Actions take arbitrary form input _and_ return arbitrary responses, thus satisfying the needs of both Config and Properties, which will be removed in a future release. This gives packages developers the ability to break up Config and Properties into smaller, more specific formats, or to exclude them entirely without polluting the UI.
|
||||
Actions take arbitrary form input and return arbitrary responses, thus satisfying the needs of both Config and Properties, which have been removed. The new actions API gives packages developers the ability to break up Config and Properties into smaller, more specific formats, or to exclude them entirely without polluting the UI. Improved form design and new input types round out the actions experience.
|
||||
|
||||
### Squashfs updates
|
||||
|
||||
StartOS now uses squashfs images to represent OS updates. This allows for better update verification, and improved reliability over rsync updates.
|
||||
|
||||
### Typescript package API and SDK
|
||||
### Typescript SDK
|
||||
|
||||
StartOS now exposes a Typescript API. Package developers can take advantage in a simple, typesafe way using the new start-sdk. A barebones StartOS package (s9pk) can be produced in minutes with minimal knowledge or skill. More advanced developers can use the SDK to create highly customized user experiences with their service.
|
||||
Package developers can now take advantage of StartOS APIs using the new start-sdk, available in Typescript. A barebones StartOS package (s9pk) can be produced in minutes with minimal knowledge or skill. More advanced developers can use the SDK to create highly customized user experiences with their service.
|
||||
|
||||
### Remove PostgresSQL
|
||||
|
||||
@@ -76,8 +71,14 @@ The new start-fs fuse module unifies file system expectations for various platfo
|
||||
|
||||
### Exver
|
||||
|
||||
StartOS now uses Extended Versioning (Exver), which consists of three parts, separated by semicolons: (1) a Semver-compliant upstream version, (2) a Semver-compliant wrapper version, and (3) an optional "flavor" prefix. Flavors can be thought of as alternative implementations of services, where a user would only want one or the other installed, and data can feasibly be migrating beetween the two. Another common characteristic of flavors is that they satisfy the same API requirement of dependents, though this is not strictly necessary. A valid Exver looks something like this: `#knots:28.0.:1.0-beta.1`. This would translate to "the first beta release of StartOS wrapper version 1.0 of Bitcoin Knots version 27.0".
|
||||
StartOS now uses Extended Versioning (Exver), which consists of three parts: (1) a Semver-compliant upstream version, (2) a Semver-compliant wrapper version, and (3) an optional "flavor" prefix. Flavors can be thought of as alternative implementations of services, where a user would only want one or the other installed, and data can feasibly be migrating between the two. Another common characteristic of flavors is that they satisfy the same API requirement of dependents, though this is not strictly necessary. A valid Exver looks something like this: `#knots:28.0.:1.0-beta.1`. This would translate to "the first beta release of StartOS wrapper version 1.0 of Bitcoin Knots version 27.0".
|
||||
|
||||
### Clearnet
|
||||
|
||||
It is now possible, and quite easy, to expose specific services interfaces to the public Internet on a standard domain using start-cli. This functionality will be expanded upon and moved into the StartOS UI in a future release.
|
||||
It is now possible, and quite easy, to expose service interfaces to the public Internet on a standard domain using start-cli. In addition to choosing which service interfaces to expose on which domains/subdomains, users have two options:
|
||||
|
||||
1. Open ports on their router. This option is free and easy to accomplish with most routers. The drawback is that the user's home IP address is revealed to anyone accessing the exposes resources. For example, hosting a blog in this way would reveal your home IP address, and therefor your approximate location on Earth, to your readers.
|
||||
|
||||
2. Use a Wireguard VPN to proxy web traffic. This option requires the user to provision a $5-$10/month remote VPS and perform a few, simple commands. The result is the successful obfuscation of the users home IP address.
|
||||
|
||||
The CLI-driven clearnet functionality will be expanded upon and moved into the main StartOS UI in a future release.
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::future::Future;
|
||||
use std::path::Path;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use const_format::formatcp;
|
||||
use ed25519_dalek::SigningKey;
|
||||
use exver::{PreReleaseSegment, VersionRange};
|
||||
use imbl_value::{json, InternedString};
|
||||
use itertools::Itertools;
|
||||
use models::PackageId;
|
||||
use openssl::pkey::{PKey, Private};
|
||||
use openssl::pkey::PKey;
|
||||
use openssl::x509::X509;
|
||||
use patch_db::ModelExt;
|
||||
use sqlx::postgres::PgConnectOptions;
|
||||
use sqlx::{PgPool, Row};
|
||||
use ssh_key::Fingerprint;
|
||||
use tokio::process::Command;
|
||||
use torut::onion::TorSecretKeyV3;
|
||||
|
||||
@@ -23,15 +20,11 @@ use crate::account::AccountInfo;
|
||||
use crate::auth::Sessions;
|
||||
use crate::backup::target::cifs::CifsTargets;
|
||||
use crate::context::RpcContext;
|
||||
use crate::db::model::Database;
|
||||
use crate::disk::mount::filesystem::cifs::Cifs;
|
||||
use crate::disk::mount::util::unmount;
|
||||
use crate::hostname::Hostname;
|
||||
use crate::net::forward::AvailablePorts;
|
||||
use crate::net::keys::KeyStore;
|
||||
use crate::net::ssl::CertStore;
|
||||
use crate::net::tor;
|
||||
use crate::net::tor::OnionStore;
|
||||
use crate::notifications::{Notification, Notifications};
|
||||
use crate::prelude::*;
|
||||
use crate::s9pk::merkle_archive::source::multi_cursor_file::MultiCursorFile;
|
||||
@@ -39,6 +32,7 @@ use crate::ssh::{SshKeys, SshPubKey};
|
||||
use crate::util::crypto::ed25519_expand_key;
|
||||
use crate::util::serde::{Pem, PemEncoding};
|
||||
use crate::util::Invoke;
|
||||
use crate::{DATA_DIR, PACKAGE_DATA};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref V0_3_6_alpha_0: exver::Version = exver::Version::new(
|
||||
@@ -191,7 +185,6 @@ async fn init_postgres(datadir: impl AsRef<Path>) -> Result<PgPool, Error> {
|
||||
.run(&secret_store)
|
||||
.await
|
||||
.with_kind(crate::ErrorKind::Database)?;
|
||||
dbg!("Init Postgres Done");
|
||||
Ok(secret_store)
|
||||
}
|
||||
|
||||
@@ -200,7 +193,7 @@ pub struct Version;
|
||||
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_5_2::Version;
|
||||
type PreUpRes = (AccountInfo, SshKeys, CifsTargets, Notifications);
|
||||
type PreUpRes = (AccountInfo, SshKeys, CifsTargets);
|
||||
fn semver(self) -> exver::Version {
|
||||
V0_3_6_alpha_0.clone()
|
||||
}
|
||||
@@ -208,22 +201,16 @@ impl VersionT for Version {
|
||||
&V0_3_0_COMPAT
|
||||
}
|
||||
async fn pre_up(self) -> Result<Self::PreUpRes, Error> {
|
||||
let pg = init_postgres("/embassy-data").await?;
|
||||
let pg = init_postgres(DATA_DIR).await?;
|
||||
let account = previous_account_info(&pg).await?;
|
||||
|
||||
let ssh_keys = previous_ssh_keys(&pg).await?;
|
||||
|
||||
let cifs = previous_cifs(&pg).await?;
|
||||
|
||||
let notifications = previous_notifications(pg).await?;
|
||||
|
||||
Ok((account, ssh_keys, cifs, notifications))
|
||||
Ok((account, ssh_keys, cifs))
|
||||
}
|
||||
fn up(
|
||||
self,
|
||||
db: &mut Value,
|
||||
(account, ssh_keys, cifs, notifications): Self::PreUpRes,
|
||||
) -> Result<(), Error> {
|
||||
fn up(self, db: &mut Value, (account, ssh_keys, cifs): Self::PreUpRes) -> Result<(), Error> {
|
||||
let wifi = json!({
|
||||
"infterface": db["server-info"]["wifi"]["interface"],
|
||||
"ssids": db["server-info"]["wifi"]["ssids"],
|
||||
@@ -305,7 +292,7 @@ impl VersionT for Version {
|
||||
value["sshPubkeys"] = to_value(&ssh_keys)?;
|
||||
value["availablePorts"] = to_value(&AvailablePorts::new())?;
|
||||
value["sessions"] = to_value(&Sessions::new())?;
|
||||
value["notifications"] = to_value(¬ifications)?;
|
||||
value["notifications"] = to_value(&Notifications::new())?;
|
||||
value["cifs"] = to_value(&cifs)?;
|
||||
value["packageStores"] = json!({});
|
||||
value
|
||||
@@ -315,7 +302,6 @@ impl VersionT for Version {
|
||||
"private": private,
|
||||
});
|
||||
|
||||
dbg!("Should be done with the up");
|
||||
*db = next;
|
||||
Ok(())
|
||||
}
|
||||
@@ -329,7 +315,7 @@ impl VersionT for Version {
|
||||
#[instrument(skip(self, ctx))]
|
||||
/// MUST be idempotent, and is run after *all* db migrations
|
||||
async fn post_up(self, ctx: &RpcContext) -> Result<(), Error> {
|
||||
let path = Path::new("/embassy-data/package-data/archive/");
|
||||
let path = Path::new(formatcp!("{PACKAGE_DATA}/archive/"));
|
||||
if !path.is_dir() {
|
||||
return Err(Error::new(
|
||||
eyre!(
|
||||
@@ -383,64 +369,6 @@ impl VersionT for Version {
|
||||
}
|
||||
}
|
||||
|
||||
async fn previous_notifications(pg: sqlx::Pool<sqlx::Postgres>) -> Result<Notifications, Error> {
|
||||
let notification_cursor = sqlx::query(r#"SELECT * FROM notifications"#)
|
||||
.fetch_all(&pg)
|
||||
.await?;
|
||||
let notifications = {
|
||||
let mut notifications = Notifications::default();
|
||||
for row in notification_cursor {
|
||||
let package_id = serde_json::from_str::<PackageId>(
|
||||
row.try_get("package_id")
|
||||
.with_ctx(|_| (ErrorKind::Database, "package_id"))?,
|
||||
)
|
||||
.ok();
|
||||
|
||||
let created_at = row
|
||||
.try_get("created_at")
|
||||
.with_ctx(|_| (ErrorKind::Database, "created_at"))?;
|
||||
let code = row
|
||||
.try_get::<i64, _>("code")
|
||||
.with_ctx(|_| (ErrorKind::Database, "code"))? as u32;
|
||||
let id = row
|
||||
.try_get::<i64, _>("id")
|
||||
.with_ctx(|_| (ErrorKind::Database, "id"))? as u32;
|
||||
let level = serde_json::from_str(
|
||||
row.try_get("level")
|
||||
.with_ctx(|_| (ErrorKind::Database, "level"))?,
|
||||
)
|
||||
.with_kind(ErrorKind::Database)
|
||||
.with_ctx(|_| (ErrorKind::Database, "level: serde_json "))?;
|
||||
let title = row
|
||||
.try_get("title")
|
||||
.with_ctx(|_| (ErrorKind::Database, "title"))?;
|
||||
let message = row
|
||||
.try_get("message")
|
||||
.with_ctx(|_| (ErrorKind::Database, "message"))?;
|
||||
let data = serde_json::from_str(
|
||||
row.try_get("data")
|
||||
.with_ctx(|_| (ErrorKind::Database, "data"))?,
|
||||
)
|
||||
.unwrap_or_default();
|
||||
|
||||
notifications.0.insert(
|
||||
id,
|
||||
Notification {
|
||||
package_id,
|
||||
created_at,
|
||||
code,
|
||||
level,
|
||||
title,
|
||||
message,
|
||||
data,
|
||||
},
|
||||
);
|
||||
}
|
||||
notifications
|
||||
};
|
||||
Ok(notifications)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn previous_cifs(pg: &sqlx::Pool<sqlx::Postgres>) -> Result<CifsTargets, Error> {
|
||||
let cifs = sqlx::query(r#"SELECT * FROM cifs_shares"#)
|
||||
@@ -448,16 +376,17 @@ async fn previous_cifs(pg: &sqlx::Pool<sqlx::Postgres>) -> Result<CifsTargets, E
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|row| {
|
||||
let id: i64 = row.try_get("id")?;
|
||||
let id: i32 = row.try_get("id")?;
|
||||
Ok::<_, Error>((
|
||||
id,
|
||||
Cifs {
|
||||
hostname: row
|
||||
.try_get("hostname")
|
||||
.with_ctx(|_| (ErrorKind::Database, "hostname"))?,
|
||||
path: serde_json::from_str(row.try_get("path")?)
|
||||
.with_kind(ErrorKind::Database)
|
||||
.with_ctx(|_| (ErrorKind::Database, "path"))?,
|
||||
path: row
|
||||
.try_get::<String, _>("path")
|
||||
.with_ctx(|_| (ErrorKind::Database, "path"))?
|
||||
.into(),
|
||||
username: row
|
||||
.try_get("username")
|
||||
.with_ctx(|_| (ErrorKind::Database, "username"))?,
|
||||
@@ -486,7 +415,7 @@ async fn previous_account_info(pg: &sqlx::Pool<sqlx::Postgres>) -> Result<Accoun
|
||||
password: account_query
|
||||
.try_get("password")
|
||||
.with_ctx(|_| (ErrorKind::Database, "password"))?,
|
||||
tor_key: TorSecretKeyV3::try_from(
|
||||
tor_keys: vec![TorSecretKeyV3::try_from(
|
||||
if let Some(bytes) = account_query
|
||||
.try_get::<Option<Vec<u8>>, _>("tor_key")
|
||||
.with_ctx(|_| (ErrorKind::Database, "tor_key"))?
|
||||
@@ -511,7 +440,7 @@ async fn previous_account_info(pg: &sqlx::Pool<sqlx::Postgres>) -> Result<Accoun
|
||||
.with_ctx(|_| (ErrorKind::Database, "password.u8 32"))?,
|
||||
)
|
||||
},
|
||||
)?,
|
||||
)?],
|
||||
server_id: account_query
|
||||
.try_get("server_id")
|
||||
.with_ctx(|_| (ErrorKind::Database, "server_id"))?,
|
||||
|
||||
94
core/startos/src/version/v0_3_6_alpha_10.rs
Normal file
94
core/startos/src/version/v0_3_6_alpha_10.rs
Normal file
@@ -0,0 +1,94 @@
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use exver::{PreReleaseSegment, VersionRange};
|
||||
use imbl_value::InternedString;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use torut::onion::OnionAddressV3;
|
||||
|
||||
use super::v0_3_5::V0_3_0_COMPAT;
|
||||
use super::{v0_3_6_alpha_9, VersionT};
|
||||
use crate::net::host::address::DomainConfig;
|
||||
use crate::prelude::*;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref V0_3_6_alpha_10: exver::Version = exver::Version::new(
|
||||
[0, 3, 6],
|
||||
[PreReleaseSegment::String("alpha".into()), 10.into()]
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(tag = "kind")]
|
||||
enum HostAddress {
|
||||
Onion { address: OnionAddressV3 },
|
||||
Domain { address: InternedString },
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct Version;
|
||||
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_6_alpha_9::Version;
|
||||
type PreUpRes = ();
|
||||
|
||||
async fn pre_up(self) -> Result<Self::PreUpRes, Error> {
|
||||
Ok(())
|
||||
}
|
||||
fn semver(self) -> exver::Version {
|
||||
V0_3_6_alpha_10.clone()
|
||||
}
|
||||
fn compat(self) -> &'static VersionRange {
|
||||
&V0_3_0_COMPAT
|
||||
}
|
||||
fn up(self, db: &mut Value, _: Self::PreUpRes) -> Result<(), Error> {
|
||||
for (_, package) in db["public"]["packageData"]
|
||||
.as_object_mut()
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("expected public.packageData to be an object"),
|
||||
ErrorKind::Database,
|
||||
)
|
||||
})?
|
||||
.iter_mut()
|
||||
{
|
||||
for (_, host) in package["hosts"]
|
||||
.as_object_mut()
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("expected public.packageData[id].hosts to be an object"),
|
||||
ErrorKind::Database,
|
||||
)
|
||||
})?
|
||||
.iter_mut()
|
||||
{
|
||||
let mut onions = BTreeSet::new();
|
||||
let mut domains = BTreeMap::new();
|
||||
let addresses = from_value::<BTreeSet<HostAddress>>(host["addresses"].clone())?;
|
||||
for address in addresses {
|
||||
match address {
|
||||
HostAddress::Onion { address } => {
|
||||
onions.insert(address);
|
||||
}
|
||||
HostAddress::Domain { address } => {
|
||||
domains.insert(
|
||||
address,
|
||||
DomainConfig {
|
||||
public: true,
|
||||
acme: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
host["onions"] = to_value(&onions)?;
|
||||
host["domains"] = to_value(&domains)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn down(self, _db: &mut Value) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
83
core/startos/src/version/v0_3_6_alpha_11.rs
Normal file
83
core/startos/src/version/v0_3_6_alpha_11.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
use exver::{PreReleaseSegment, VersionRange};
|
||||
use imbl_value::json;
|
||||
|
||||
use super::v0_3_5::V0_3_0_COMPAT;
|
||||
use super::{v0_3_6_alpha_10, VersionT};
|
||||
use crate::prelude::*;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref V0_3_6_alpha_11: exver::Version = exver::Version::new(
|
||||
[0, 3, 6],
|
||||
[PreReleaseSegment::String("alpha".into()), 11.into()]
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct Version;
|
||||
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_6_alpha_10::Version;
|
||||
type PreUpRes = ();
|
||||
|
||||
async fn pre_up(self) -> Result<Self::PreUpRes, Error> {
|
||||
Ok(())
|
||||
}
|
||||
fn semver(self) -> exver::Version {
|
||||
V0_3_6_alpha_11.clone()
|
||||
}
|
||||
fn compat(self) -> &'static VersionRange {
|
||||
&V0_3_0_COMPAT
|
||||
}
|
||||
fn up(self, db: &mut Value, _: Self::PreUpRes) -> Result<(), Error> {
|
||||
let acme = std::mem::replace(
|
||||
&mut db["public"]["serverInfo"]["acme"],
|
||||
Value::Object(Default::default()),
|
||||
);
|
||||
if !acme.is_null() && acme["provider"].as_str().is_some() {
|
||||
db["public"]["serverInfo"]["acme"]
|
||||
[&acme["provider"].as_str().or_not_found("provider")?] =
|
||||
json!({ "contact": &acme["contact"] });
|
||||
}
|
||||
|
||||
for (_, package) in db["public"]["packageData"]
|
||||
.as_object_mut()
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("expected public.packageData to be an object"),
|
||||
ErrorKind::Database,
|
||||
)
|
||||
})?
|
||||
.iter_mut()
|
||||
{
|
||||
for (_, host) in package["hosts"]
|
||||
.as_object_mut()
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("expected public.packageData[id].hosts to be an object"),
|
||||
ErrorKind::Database,
|
||||
)
|
||||
})?
|
||||
.iter_mut()
|
||||
{
|
||||
for (_, bind) in host["bindings"]
|
||||
.as_object_mut()
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
eyre!("expected public.packageData[id].hosts[hostId].bindings to be an object"),
|
||||
ErrorKind::Database,
|
||||
)
|
||||
})?
|
||||
.iter_mut()
|
||||
{
|
||||
bind["net"] = bind["lan"].clone();
|
||||
bind["net"]["public"] = Value::Bool(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn down(self, _db: &mut Value) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
68
core/startos/src/version/v0_3_6_alpha_12.rs
Normal file
68
core/startos/src/version/v0_3_6_alpha_12.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use exver::{PreReleaseSegment, VersionRange};
|
||||
use imbl_value::json;
|
||||
|
||||
use super::v0_3_5::V0_3_0_COMPAT;
|
||||
use super::{v0_3_6_alpha_11, VersionT};
|
||||
use crate::prelude::*;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref V0_3_6_alpha_12: exver::Version = exver::Version::new(
|
||||
[0, 3, 6],
|
||||
[PreReleaseSegment::String("alpha".into()), 12.into()]
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct Version;
|
||||
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_6_alpha_11::Version;
|
||||
type PreUpRes = ();
|
||||
|
||||
async fn pre_up(self) -> Result<Self::PreUpRes, Error> {
|
||||
Ok(())
|
||||
}
|
||||
fn semver(self) -> exver::Version {
|
||||
V0_3_6_alpha_12.clone()
|
||||
}
|
||||
fn compat(self) -> &'static VersionRange {
|
||||
&V0_3_0_COMPAT
|
||||
}
|
||||
fn up(self, db: &mut Value, _: Self::PreUpRes) -> Result<(), Error> {
|
||||
let bindings: BTreeMap<u16, Value> = [(
|
||||
80,
|
||||
json!({
|
||||
"enabled": false,
|
||||
"options": {
|
||||
"preferredExternalPort": 80,
|
||||
"addSsl": {
|
||||
"preferredExternalPort": 443,
|
||||
"alpn": { "specified": [ "http/1.1", "h2" ] },
|
||||
},
|
||||
"secure": null,
|
||||
},
|
||||
"net": {
|
||||
"assignedPort": null,
|
||||
"assignedSslPort": 443,
|
||||
"public": false,
|
||||
}
|
||||
}),
|
||||
)]
|
||||
.into_iter()
|
||||
.collect();
|
||||
let onion = db["public"]["serverInfo"]["onionAddress"].clone();
|
||||
db["public"]["serverInfo"]["host"] = json!({
|
||||
"bindings": bindings,
|
||||
"onions": [onion],
|
||||
"domains": {},
|
||||
"hostnameInfo": {},
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn down(self, _db: &mut Value) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
39
core/startos/src/version/v0_3_6_alpha_13.rs
Normal file
39
core/startos/src/version/v0_3_6_alpha_13.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use exver::{PreReleaseSegment, VersionRange};
|
||||
use imbl_value::json;
|
||||
|
||||
use super::v0_3_5::V0_3_0_COMPAT;
|
||||
use super::{v0_3_6_alpha_12, VersionT};
|
||||
use crate::prelude::*;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref V0_3_6_alpha_13: exver::Version = exver::Version::new(
|
||||
[0, 3, 6],
|
||||
[PreReleaseSegment::String("alpha".into()), 13.into()]
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct Version;
|
||||
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_6_alpha_12::Version;
|
||||
type PreUpRes = ();
|
||||
|
||||
async fn pre_up(self) -> Result<Self::PreUpRes, Error> {
|
||||
Ok(())
|
||||
}
|
||||
fn semver(self) -> exver::Version {
|
||||
V0_3_6_alpha_13.clone()
|
||||
}
|
||||
fn compat(self) -> &'static VersionRange {
|
||||
&V0_3_0_COMPAT
|
||||
}
|
||||
fn up(self, db: &mut Value, _: Self::PreUpRes) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
fn down(self, _db: &mut Value) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ impl VersionT for Version {
|
||||
async fn pre_up(self) -> Result<Self::PreUpRes, Error> {
|
||||
Ok(())
|
||||
}
|
||||
fn up(self, db: &mut Value, _: Self::PreUpRes) -> Result<(), Error> {
|
||||
fn up(self, _db: &mut Value, _: Self::PreUpRes) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn post_up<'a>(self, ctx: &'a crate::context::RpcContext) -> Result<(), Error> {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use exver::{PreReleaseSegment, VersionRange};
|
||||
use imbl_value::{json, InOMap};
|
||||
use imbl_value::json;
|
||||
use tokio::process::Command;
|
||||
|
||||
use super::v0_3_5::V0_3_0_COMPAT;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::path::Path;
|
||||
|
||||
use exver::{PreReleaseSegment, VersionRange};
|
||||
use tokio::fs::File;
|
||||
|
||||
@@ -12,6 +14,7 @@ use crate::s9pk::v2::SIG_CONTEXT;
|
||||
use crate::s9pk::S9pk;
|
||||
use crate::service::LoadDisposition;
|
||||
use crate::util::io::create_file;
|
||||
use crate::DATA_DIR;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref V0_3_6_alpha_8: exver::Version = exver::Version::new(
|
||||
@@ -40,7 +43,7 @@ impl VersionT for Version {
|
||||
Ok(())
|
||||
}
|
||||
async fn post_up(self, ctx: &crate::context::RpcContext) -> Result<(), Error> {
|
||||
let s9pk_dir = ctx.datadir.join(PKG_ARCHIVE_DIR).join("installed");
|
||||
let s9pk_dir = Path::new(DATA_DIR).join(PKG_ARCHIVE_DIR).join("installed");
|
||||
|
||||
if tokio::fs::metadata(&s9pk_dir).await.is_ok() {
|
||||
let mut read_dir = tokio::fs::read_dir(&s9pk_dir).await?;
|
||||
|
||||
Reference in New Issue
Block a user