Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions crates/observer-app/src/supervision/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ use observer_domain::convars::CfgConvars;
use observer_domain::error::{ApiError, ErrorCode};
use observer_domain::launch::{LaunchChange, OneSync, StoredLaunch};
use observer_domain::server_data::{
CfgCheck, CfgFinding, CfgReport, Discovery, EndpointProtocol, FindingKind, FolderCheck, FolderListing,
FolderQuery, FolderReport, LicenceState, Place, PlaceKind, Severity,
CfgCheck, CfgFinding, CfgReport, CfgText, CfgTextQuery, Discovery, EndpointProtocol, FileListing,
FilesQuery, FindingKind, FolderCheck, FolderListing, FolderQuery, FolderReport, LicenceState, Place,
PlaceKind, Severity,
};
use observer_fxserver::cfg::Context;
use observer_fxserver::folders::{self, Search};
use observer_fxserver::layout::{Flavour, Layout};
use observer_fxserver::server_data;
use observer_fxserver::{server_data, server_files};

use super::{Supervision, read_launch};
use crate::servers::follow_rules;
Expand Down Expand Up @@ -48,6 +49,26 @@ impl Supervision {
blocking(move || folders::list(&query, &observer)).await
}

/// The entries of one folder of a server folder, for the setup's file browser. It changes
/// nothing.
pub async fn list_files(&self, query: FilesQuery) -> Result<FileListing, Error> {
let _turn = self
.inner
.folder_reads
.acquire()
.await
.map_err(io::Error::other)?;
let observer = self.inner.data_dir.clone();
blocking(move || server_files::list(&query.data_path, &query.path, &observer)).await
}

/// A cfg of a server folder with its secrets left out, for the setup to show. It changes
/// nothing.
pub async fn cfg_text(&self, query: CfgTextQuery) -> Result<CfgText, Error> {
let observer = self.inner.data_dir.clone();
blocking(move || server_files::cfg_text(&query.data_path, &query.cfg_file, &observer)).await
}

/// Searches the home folder and the local drives for servers, and names the places the owner
/// may browse from. It changes nothing.
pub async fn discover(&self) -> Result<Discovery, Error> {
Expand Down
89 changes: 89 additions & 0 deletions crates/observer-domain/src/server_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,95 @@ pub enum CfgFileProblem {
TooLarge,
}

/// `POST /api/servers/default/setup/files`: the entries of one folder of a server folder, for the
/// setup's file browser.
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, TS)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[ts(export)]
pub struct FilesQuery {
pub data_path: String,
/// Relative to the data folder with `/`; empty for the data folder itself.
#[serde(default)]
pub path: String,
}

/// One folder of a server folder, as the setup's file browser shows it.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct FileListing {
/// The folder listed, as asked.
pub path: String,
/// The data folder's problem, or why this folder cannot be listed: `invalidPath`, `missing`,
/// `notAFolder`, `unreadable` (a link, or a folder Observer never opens) or `insideObserver`.
pub problem: Option<FolderProblem>,
/// Folders first, then files, by name, case aside.
pub entries: Vec<FileEntry>,
/// More entries than the 500 listed.
pub truncated: bool,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct FileEntry {
pub name: String,
/// Relative to the data folder with `/`.
pub path: String,
pub kind: FileEntryKind,
/// A link or a junction, which the browser never follows.
pub link: bool,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum FileEntryKind {
Folder,
/// A `.cfg` file, which the setup reads.
Cfg,
/// Any other file: listed, never read.
File,
/// What holds secrets or belongs to FXServer or Observer: `cache`, txAdmin's data, `.env`
/// and key files, Observer's own folder. Listed so the owner sees it is there, never opened.
Withheld,
}

/// `POST /api/servers/default/setup/cfg/text`.
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, TS)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[ts(export)]
pub struct CfgTextQuery {
pub data_path: String,
/// Relative to the data folder.
pub cfg_file: String,
}

/// A cfg as the setup shows it, with its secrets left out.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct CfgText {
/// The data folder's own problem: with one, the cfg is not read.
pub folder: Option<FolderProblem>,
pub problem: Option<CfgFileProblem>,
/// Why the path rules refuse it, with `invalidPath`.
pub path_problem: Option<LaunchProblem>,
/// Each line, cut where a secret was: the secret itself never leaves Observer.
pub lines: Vec<Vec<CfgSpan>>,
/// The file has more lines than the 2,000 shown.
pub truncated: bool,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct CfgSpan {
/// Empty for a secret.
pub text: String,
pub secret: bool,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, TS)]
#[ts(export)]
pub struct CfgFile {
Expand Down
1 change: 1 addition & 0 deletions crates/observer-fxserver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub mod players;
pub mod pre_launch;
pub mod recovery;
pub mod server_data;
pub mod server_files;
pub mod stdin;
pub mod supervisor;
pub mod trace;
Expand Down
Loading
Loading