Skip to content
This repository has been archived by the owner on Dec 21, 2024. It is now read-only.

chore(toolchain): remove requirement to be signed in for toolchain tasks #503

Closed
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
15 changes: 6 additions & 9 deletions packages/cli/src/commands/db/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ use clap::Parser;
use clap::Subcommand;
use serde::Serialize;
use std::process::ExitCode;
use toolchain::tasks::postgres_reset;
use toolchain::tasks::postgres_start;
use toolchain::tasks::postgres_status;
use toolchain::tasks::postgres_stop;
use toolchain::tasks;

use crate::util::task::run_task;
use crate::util::task::run_task_simple;
Expand Down Expand Up @@ -38,7 +35,7 @@ pub struct StartOpts {}

impl StartOpts {
pub async fn execute(&self) -> ExitCode {
run_task_simple::<postgres_start::Task>(postgres_start::Input {}).await
run_task_simple::<tasks::postgres::start::Task>(tasks::postgres::start::Input {}).await
}
}

Expand All @@ -49,7 +46,7 @@ pub struct StopOpts {}

impl StopOpts {
pub async fn execute(&self) -> ExitCode {
run_task_simple::<postgres_stop::Task>(postgres_stop::Input {}).await
run_task_simple::<tasks::postgres::stop::Task>(tasks::postgres::stop::Input {}).await
}
}

Expand All @@ -60,9 +57,9 @@ pub struct StatusOpts {}

impl StatusOpts {
pub async fn execute(&self) -> ExitCode {
match run_task::<postgres_status::Task>(
match run_task::<tasks::postgres::status::Task>(
TaskOutputStyle::PlainNoResult,
postgres_status::Input {},
tasks::postgres::status::Input {},
)
.await
{
Expand All @@ -85,6 +82,6 @@ pub struct ResetOpts {}

impl ResetOpts {
pub async fn execute(&self) -> ExitCode {
run_task_simple::<postgres_reset::Task>(postgres_reset::Input {}).await
run_task_simple::<tasks::postgres::reset::Task>(tasks::postgres::reset::Input {}).await
}
}
8 changes: 6 additions & 2 deletions packages/cli/src/commands/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,13 @@ impl Opts {
return ExitCode::FAILURE;
}
};
let Some(cloud_data) = bootstrap_data.cloud else {
eprintln!("Not signed in");
return ExitCode::FAILURE;
};

// Find environment
let environment = match bootstrap_data
let environment = match cloud_data
.envs
.iter()
.find(|env| env.slug == self.environment)
Expand All @@ -43,7 +47,7 @@ impl Opts {
"Environment '{}' not found. Available environments:",
self.environment
);
for env in &bootstrap_data.envs {
for env in &cloud_data.envs {
eprintln!("- {}", env.slug);
}
return ExitCode::FAILURE;
Expand Down
16 changes: 9 additions & 7 deletions packages/cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@ pub mod db;
pub mod deploy;
pub mod dev;
pub mod init;
pub mod login;
pub mod logout;
pub mod module;
pub mod sign_in;
pub mod sign_out;
pub mod task;

use clap::Parser;
use std::process::ExitCode;

#[derive(Parser)]
pub enum SubCommand {
Init(login::Opts),
Login(login::Opts),
Logout(logout::Opts),
Init(init::Opts),
#[clap(alias = "login")]
Signin(sign_in::Opts),
#[clap(alias = "logout")]
Signout(sign_out::Opts),
Dev(dev::Opts),
Deploy(deploy::Opts),
Config {
Expand Down Expand Up @@ -52,8 +54,8 @@ impl SubCommand {
pub async fn execute(&self) -> ExitCode {
match self {
SubCommand::Init(opts) => opts.execute().await,
SubCommand::Login(opts) => opts.execute().await,
SubCommand::Logout(opts) => opts.execute().await,
SubCommand::Signin(opts) => opts.execute().await,
SubCommand::Signout(opts) => opts.execute().await,
SubCommand::Dev(opts) => opts.execute().await,
SubCommand::Deploy(opts) => opts.execute().await,
SubCommand::Config { subcommand } => subcommand.execute().await,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clap::Parser;
use std::process::ExitCode;
use toolchain::tasks::{check_login_state, start_device_link, wait_for_login};
use toolchain::tasks;

use crate::util::task::{run_task, TaskOutputStyle};

Expand All @@ -14,15 +14,15 @@ pub struct Opts {
impl Opts {
pub async fn execute(&self) -> ExitCode {
// Check if linked
match run_task::<check_login_state::Task>(
match run_task::<tasks::auth::check_state::Task>(
TaskOutputStyle::None,
check_login_state::Input {},
tasks::auth::check_state::Input {},
)
.await
{
Ok(output) => {
if output.logged_in {
eprintln!("Already logged in. Sign out with `rivet unlink`.");
if output.signed_in {
eprintln!("Already logged in. Sign out with `rivet logout`.");
return ExitCode::SUCCESS;
}
}
Expand All @@ -33,9 +33,9 @@ impl Opts {
}

// Start device link
let device_link_output = match run_task::<start_device_link::Task>(
let device_link_output = match run_task::<tasks::auth::start_sign_in::Task>(
TaskOutputStyle::None,
start_device_link::Input {
tasks::auth::start_sign_in::Input {
api_endpoint: self.api_endpoint.clone(),
},
)
Expand All @@ -50,9 +50,9 @@ impl Opts {
eprintln!("{}", device_link_output.device_link_url);

// Wait for finish
match run_task::<wait_for_login::Task>(
match run_task::<tasks::auth::wait_for_sign_in::Task>(
TaskOutputStyle::None,
wait_for_login::Input {
tasks::auth::wait_for_sign_in::Input {
api_endpoint: self.api_endpoint.clone(),
device_link_token: device_link_output.device_link_token,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clap::Parser;
use std::process::ExitCode;
use toolchain::tasks::unlink;
use toolchain::tasks;

use crate::util::task::{run_task, TaskOutputStyle};

Expand All @@ -10,7 +10,12 @@ pub struct Opts {}

impl Opts {
pub async fn execute(&self) -> ExitCode {
match run_task::<unlink::Task>(TaskOutputStyle::None, unlink::Input {}).await {
match run_task::<tasks::auth::sign_out::Task>(
TaskOutputStyle::None,
tasks::auth::sign_out::Input {},
)
.await
{
Ok(_) => {
eprintln!("Logged out");
ExitCode::SUCCESS
Expand Down
18 changes: 15 additions & 3 deletions packages/toolchain/src/backend/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,15 @@ pub async fn provision_database(
.await?;

// Fetch remote DB URL
let mut env_config = config::meta::mutate_project(&paths::data_dir()?, |config| {
config.environments.entry(env_id).or_default().clone()
let mut env_config = config::meta::try_mutate_project(&paths::data_dir()?, |config| {
Ok(config
.cloud
.as_mut()
.context("config.cloud")?
.environments
.entry(env_id)
.or_default()
.clone())
})
.await?;

Expand All @@ -39,7 +46,12 @@ pub async fn provision_database(

// Update cache
config::meta::try_mutate_project(&paths::data_dir()?, |config| {
config.environments.insert(env_id, env_config.clone());
config
.cloud
.as_mut()
.context("config.cloud")?
.environments
.insert(env_id, env_config.clone());
Ok(())
})
.await?;
Expand Down
109 changes: 23 additions & 86 deletions packages/toolchain/src/config/meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,12 @@ use uuid::Uuid;
use crate::paths;

/// Config stored in {data_dir}/meta.json. Used to store persistent data, such as tokens & cache.
#[derive(Serialize, Deserialize)]
#[derive(Default, Serialize, Deserialize)]
pub struct Meta {
pub cluster: Cluster,
pub tokens: Tokens,
pub environments: HashMap<Uuid, Environment>,

/// Stores the state for all of the processes.
/// If signed in to Rivet, this will include relevant information.
///
/// Key is the key in the `ProcessManager` config.
#[serde(default)]
pub processes: HashMap<String, ProcessState>,
/// If not signed in, will be None.
pub cloud: Option<Cloud>,

/// Port which the dev server is running on for plugins.
#[serde(default)]
Expand All @@ -29,28 +24,26 @@ pub struct Meta {
pub editor_port: Option<u16>,
}

impl Meta {
fn new(api_endpoint: String, cloud_token: String) -> Self {
Meta {
cluster: Cluster { api_endpoint },
tokens: Tokens { cloud: cloud_token },
environments: HashMap::new(),
processes: HashMap::new(),
backend_port: None,
editor_port: None,
}
}
}

#[derive(Default, Serialize, Deserialize)]
pub struct Cluster {
#[derive(Serialize, Deserialize)]
pub struct Cloud {
/// Rivet API endpoint to connect to.
pub api_endpoint: String,
}

#[derive(Serialize, Deserialize)]
pub struct Tokens {
/// Cloud token used to authenticate all API requests.
pub cloud: String,
pub cloud_token: String,

/// Cache of all environments for this game.
pub environments: HashMap<Uuid, Environment>,
}

impl Cloud {
pub fn new(api_endpoint: String, cloud_token: String) -> Self {
Self {
api_endpoint,
cloud_token,
environments: HashMap::new(),
}
}
}

#[derive(Default, Clone, Serialize, Deserialize)]
Expand All @@ -65,14 +58,6 @@ pub struct Backend {
pub db_url: Option<String>,
}

#[derive(Default, Clone, Serialize, Deserialize)]
pub struct ProcessState {
/// ID of the running process.
///
/// This is not the same as the PID.
pub process_id: Option<Uuid>,
}

lazy_static! {
/// List of all meta paths cached in memory.
///
Expand Down Expand Up @@ -115,9 +100,7 @@ pub async fn try_read_project<F: FnOnce(&Meta) -> Result<T>, T>(
let mut meta = match fs::read_to_string(&meta_path).await {
Result::Ok(config) => serde_json::from_str::<Meta>(&config)
.context(format!("deserialize meta ({})", meta_path.display()))?,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
bail!("project not initialized")
}
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Meta::default(),
Err(err) => return Err(err.into()),
};

Expand Down Expand Up @@ -152,9 +135,7 @@ pub async fn try_mutate_project<F: FnOnce(&mut Meta) -> Result<T>, T>(
let mut meta = match fs::read_to_string(&meta_path).await {
Result::Ok(config) => serde_json::from_str::<Meta>(&config)
.context(format!("deserialize meta ({})", meta_path.display()))?,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
bail!("project not initialized")
}
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Meta::default(),
Err(err) => return Err(err.into()),
};

Expand All @@ -180,47 +161,3 @@ pub async fn mutate_project<F: FnOnce(&mut Meta) -> T, T>(
) -> Result<T> {
try_mutate_project(base_data_dir, |x| Ok(cb(x))).await
}

pub async fn has_project(base_data_dir: &PathBuf) -> Result<bool> {
let meta_path = paths::meta_config_file(base_data_dir)?;
let has_project = fs::try_exists(&meta_path).await?;
Ok(has_project)
}

pub async fn insert_project(
base_data_dir: &PathBuf,
api_endpoint: String,
cloud_token: String,
) -> Result<()> {
// Build and serialize
let meta = Meta::new(api_endpoint, cloud_token);
let json_str = serde_json::to_string(&meta)?;

// Write meta
//
// This will replace the existing meta
let _write_guard = META_FILE_LOCK.lock().await;
let path = paths::meta_config_file(base_data_dir)?;
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).await?;
}
fs::write(path, json_str).await?;

Ok(())
}

pub async fn delete_project(base_data_dir: &PathBuf) -> Result<()> {
let path = paths::meta_config_file(base_data_dir)?;

// Lock all resources
let mut global_meta = META.lock().await;
let _write_guard = META_FILE_LOCK.lock().await;

// Delete from cache
global_meta.remove(&path);

// Delete file
fs::remove_file(&path).await?;

Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub struct Input {}

#[derive(Serialize)]
pub struct Output {
pub logged_in: bool,
pub signed_in: bool,
}

pub struct Task;
Expand All @@ -18,11 +18,12 @@ impl task::Task for Task {
type Output = Output;

fn name() -> &'static str {
"check_login_state"
"auth.check_state"
}

async fn run(_task: task::TaskCtx, _input: Input) -> Result<Output> {
let logged_in = config::meta::has_project(&paths::data_dir()?).await?;
Ok(Output { logged_in })
let signed_in =
config::meta::read_project(&paths::data_dir()?, |meta| meta.cloud.is_some()).await?;
Ok(Output { signed_in })
}
}
Loading
Loading