Skip to content

Commit

Permalink
* Added a rustfmt.toml file. (with "acceptable" settings... it's not …
Browse files Browse the repository at this point in the history
…as customizable as eslint, so still off a fair deal from what I'd like, but it's probably close enough to be more helpful than hurtful)

* Made-so rustfmt is used by default in vscode, when rust files are saved.
* Applied rustfmt formatting throughout all .rs files in the project, by running "cargo fmt".
* Also added some `#[rustfmt::skip]` annotations, in places where the custom formatting was important for readability and/or succinctness.
  • Loading branch information
Venryx committed Jun 1, 2024
1 parent 8363ac0 commit 15163d4
Show file tree
Hide file tree
Showing 197 changed files with 13,175 additions and 12,359 deletions.
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
},
],*/

"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer",
"editor.formatOnSave": true
},
"rust-analyzer.server.extraEnv": {
// this allows us to use unstable features (as is true for the Docker builds), without rust-analyzer showing an error on the "#![feature(XXX)]" line
//"RUSTC_BOOTSTRAP": "1", // not needed anymore
Expand Down
178 changes: 89 additions & 89 deletions Packages/app-server/src/db/_general.rs
Original file line number Diff line number Diff line change
@@ -1,55 +1,55 @@
use rust_shared::anyhow::{Context, Error, anyhow, ensure};
use rust_shared::async_graphql::{Object, Schema, Subscription, ID, async_stream, OutputType, scalar, EmptySubscription, SimpleObject, InputObject};
use futures_util::{Stream, stream, TryFutureExt, StreamExt, Future};
use futures_util::{stream, Future, Stream, StreamExt, TryFutureExt};
use rust_shared::anyhow::{anyhow, ensure, Context, Error};
use rust_shared::async_graphql::{async_stream, scalar, EmptySubscription, InputObject, Object, OutputType, Schema, SimpleObject, Subscription, ID};
use rust_shared::db_constants::SYSTEM_USER_ID;
use rust_shared::indoc::indoc;
use rust_shared::rust_macros::wrap_slow_macros;
use rust_shared::db_constants::SYSTEM_USER_ID;
use rust_shared::serde::{Deserialize, Serialize};
use rust_shared::serde_json::json;
use rust_shared::tokio_postgres::Client;
use rust_shared::utils::general_::extensions::ToOwnedV;
use rust_shared::{async_graphql, serde_json, GQLError, SubError, to_sub_err};
use rust_shared::utils::type_aliases::JSONValue;
use rust_shared::serde::{Serialize, Deserialize};
use rust_shared::serde_json::json;
use rust_shared::tokio_postgres::{Client};
use tracing::{info, error, warn};
use rust_shared::{async_graphql, serde_json, to_sub_err, GQLError, SubError};
use std::env;
use std::path::Path;
use std::{time::Duration, pin::Pin, task::Poll};
use std::{pin::Pin, task::Poll, time::Duration};
use tracing::{error, info, warn};

use crate::utils::db::agql_ext::gql_request_storage::GQLRequestStorage;

use super::commands::add_term::{AddTermResult};
use super::commands::add_term::AddTermResult;
use super::commands::refresh_lq_data::refresh_lq_data;
use super::general::sign_in_::jwt_utils::{get_user_jwt_data_from_gql_ctx, resolve_and_verify_jwt_string};

/// Wrapper around `ensure!` macro, which makes it easily usable in functions that return `Result<?, GQLError>`.
pub fn ensure_gql(passed: bool, error_message: impl AsRef<str>) -> Result<(), Error> {
ensure!(passed, "{}", error_message.as_ref());
Ok(())
ensure!(passed, "{}", error_message.as_ref());
Ok(())
}

pub fn trusted_operator_passkey_is_correct(passkey: String, log_message_if_wrong: bool) -> bool {
let Ok(stored_passkey) = env::var("TRUSTED_OPERATOR_PASSKEY") else {
error!(indoc!{r#"
let Ok(stored_passkey) = env::var("TRUSTED_OPERATOR_PASSKEY") else {
error!(indoc! {r#"
The debate-map-trusted-operator secret/passkey does not exist, or is invalid!
This endpoint cannot be used until an admin fixes/creates that secret.
K8s path for secret: namespace "default", name "debate-map-trusted-provider", field "passkey", value any utf8 string
"#});
return false;
};
let result = passkey == stored_passkey;
if !result && log_message_if_wrong {
error!("Trusted-operator passkey is incorrect! Submitted:{}", passkey);
}
return result;
return false;
};
let result = passkey == stored_passkey;
if !result && log_message_if_wrong {
error!("Trusted-operator passkey is incorrect! Submitted:{}", passkey);
}
return result;
}
pub fn ensure_trusted_operator_passkey_is_correct(passkey: String, log_message_if_wrong: bool) -> Result<(), Error> {
if !trusted_operator_passkey_is_correct(passkey, log_message_if_wrong) {
return Err(anyhow!("Trusted-operator passkey is incorrect!"));
}
Ok(())
if !trusted_operator_passkey_is_correct(passkey, log_message_if_wrong) {
return Err(anyhow!("Trusted-operator passkey is incorrect!"));
}
Ok(())
}

wrap_slow_macros!{
wrap_slow_macros! {

// queries
// ==========
Expand All @@ -58,28 +58,28 @@ wrap_slow_macros!{
pub struct QueryShard_General;
#[Object]
impl QueryShard_General {
// useful for testing monitor-tool's logs page
async fn print_empty_log(&self) -> &str {
info!("print_empty_log called");
warn!("Test2");
error!("Test3");
""
}
// useful for testing monitor-tool's logs page
async fn print_empty_log(&self) -> &str {
info!("print_empty_log called");
warn!("Test2");
error!("Test3");
""
}
}

// mutations
// ==========

#[derive(Default)] pub struct MutationShard_General;
#[Object] impl MutationShard_General {
async fn refreshLQData(&self, ctx: &async_graphql::Context<'_>, payload: JSONValue) -> Result<GenericMutation_Result, GQLError> {
let result = refresh_lq_data(ctx, payload).await?;
Ok(result)
}
async fn refreshLQData(&self, ctx: &async_graphql::Context<'_>, payload: JSONValue) -> Result<GenericMutation_Result, GQLError> {
let result = refresh_lq_data(ctx, payload).await?;
Ok(result)
}
}
#[derive(SimpleObject)]
pub struct GenericMutation_Result {
pub message: String,
pub message: String,
}

// subscriptions
Expand All @@ -92,67 +92,67 @@ pub struct LinkPreserverInput {

#[derive(SimpleObject)]
struct LinkPreserverResult {
alive: bool,
// probably move effects like this (unrelated to link-preserving) into a separate subscription eventually
pageRefreshRequested: bool,
alive: bool,
// probably move effects like this (unrelated to link-preserving) into a separate subscription eventually
pageRefreshRequested: bool,
}

#[derive(SimpleObject)]
struct PingResult {
pong: String,
pong: String,
}

#[derive(Default)] pub struct SubscriptionShard_General;
#[Subscription] impl SubscriptionShard_General {
/// This endpoint serves two purposes:
/// * Keeps cloudflare from terminating the websocket for inactivity, in cases where >100s pass without data changing or the user navigating anywhere.
/// * Keeps the frontend from closing the websocket, in cases where the client is not watching any data. (eg. on homepage when not signed-in)
async fn linkPreserver(&self, _ctx: &async_graphql::Context<'_>, input: LinkPreserverInput) -> impl Stream<Item = Result<LinkPreserverResult, SubError>> {
let base_stream = async_stream::stream! {
let LinkPreserverInput { updateInterval } = input;
if (updateInterval < 10000) { Err(SubError::new(format!("Update-interval cannot be lower than 10000ms.")))?; }

let mut refresh_requested_last_iteration = Path::new("./refreshPageForAllUsers_enabled").exists();
loop {
// create the listed file in the app-server pod (eg. using Lens), if you've made an update that you need all clients to refresh for
let refresh_requested_new = Path::new("./refreshPageForAllUsers_enabled").exists();
let refresh_just_requested = refresh_requested_new && !refresh_requested_last_iteration;
let result = LinkPreserverResult {
alive: true,
pageRefreshRequested: refresh_just_requested,
};
refresh_requested_last_iteration = refresh_requested_new;

yield Ok(result);
rust_shared::tokio::time::sleep(Duration::from_millis(updateInterval)).await;
}
};
base_stream
}

// for testing (eg. in gql-playground) [temporarily also used by frontend as a websocket keep-alive -- inferior to above since doesn't work in the no-data-watched case]
#[graphql(name = "_ping")]
async fn _ping(&self, _ctx: &async_graphql::Context<'_>) -> impl Stream<Item = PingResult> {
let pong = "pong".to_owned();
stream::once(async move { PingResult {
pong,
} })
}

// for debugging only, so hide from gql api introspection
#[graphql(visible = false)]
async fn checkUser<'a>(&self, ctx: &'a async_graphql::Context<'a>) -> impl Stream<Item = Result<CheckUserResult, SubError>> + 'a {
let base_stream = async_stream::stream! {
let jwt_data = get_user_jwt_data_from_gql_ctx(ctx).await.map_err(to_sub_err)?;
yield Ok(CheckUserResult { userID: jwt_data.id });
};
base_stream
}
/// This endpoint serves two purposes:
/// * Keeps cloudflare from terminating the websocket for inactivity, in cases where >100s pass without data changing or the user navigating anywhere.
/// * Keeps the frontend from closing the websocket, in cases where the client is not watching any data. (eg. on homepage when not signed-in)
async fn linkPreserver(&self, _ctx: &async_graphql::Context<'_>, input: LinkPreserverInput) -> impl Stream<Item = Result<LinkPreserverResult, SubError>> {
let base_stream = async_stream::stream! {
let LinkPreserverInput { updateInterval } = input;
if (updateInterval < 10000) { Err(SubError::new(format!("Update-interval cannot be lower than 10000ms.")))?; }

let mut refresh_requested_last_iteration = Path::new("./refreshPageForAllUsers_enabled").exists();
loop {
// create the listed file in the app-server pod (eg. using Lens), if you've made an update that you need all clients to refresh for
let refresh_requested_new = Path::new("./refreshPageForAllUsers_enabled").exists();
let refresh_just_requested = refresh_requested_new && !refresh_requested_last_iteration;
let result = LinkPreserverResult {
alive: true,
pageRefreshRequested: refresh_just_requested,
};
refresh_requested_last_iteration = refresh_requested_new;

yield Ok(result);
rust_shared::tokio::time::sleep(Duration::from_millis(updateInterval)).await;
}
};
base_stream
}

// for testing (eg. in gql-playground) [temporarily also used by frontend as a websocket keep-alive -- inferior to above since doesn't work in the no-data-watched case]
#[graphql(name = "_ping")]
async fn _ping(&self, _ctx: &async_graphql::Context<'_>) -> impl Stream<Item = PingResult> {
let pong = "pong".to_owned();
stream::once(async move { PingResult {
pong,
} })
}

// for debugging only, so hide from gql api introspection
#[graphql(visible = false)]
async fn checkUser<'a>(&self, ctx: &'a async_graphql::Context<'a>) -> impl Stream<Item = Result<CheckUserResult, SubError>> + 'a {
let base_stream = async_stream::stream! {
let jwt_data = get_user_jwt_data_from_gql_ctx(ctx).await.map_err(to_sub_err)?;
yield Ok(CheckUserResult { userID: jwt_data.id });
};
base_stream
}
}

#[derive(SimpleObject, Debug)]
struct CheckUserResult {
userID: String,
userID: String,
}

}
}
110 changes: 60 additions & 50 deletions Packages/app-server/src/db/_shared/access_policy_target.rs
Original file line number Diff line number Diff line change
@@ -1,69 +1,79 @@
use rust_shared::{async_graphql::{self, ScalarType, InputValueResult, InputValueError, Scalar, Value}, utils::general_::extensions::ToOwnedV, serde_json};
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use rust_shared::{
async_graphql::{self, InputValueError, InputValueResult, Scalar, ScalarType, Value},
serde_json,
utils::general_::extensions::ToOwnedV,
};
use serde::{Deserialize, Deserializer, Serialize, Serializer};

use crate::db::access_policies_::_permission_set::APTable;

pub struct AccessPolicyTarget {
pub policy_id: String,
pub ap_table: APTable,
pub policy_id: String,
pub ap_table: APTable,
}
impl AccessPolicyTarget {
pub fn new(access_policy: String, table: APTable) -> Self {
Self { policy_id: access_policy, ap_table: table.o() }
}
pub fn new(access_policy: String, table: APTable) -> Self {
Self { policy_id: access_policy, ap_table: table.o() }
}
}

impl Clone for AccessPolicyTarget {
fn clone(&self) -> Self {
AccessPolicyTarget::new(self.policy_id.o(), self.ap_table)
}
fn clone(&self) -> Self {
AccessPolicyTarget::new(self.policy_id.o(), self.ap_table)
}
}
impl Serialize for AccessPolicyTarget {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
//serializer.serialize_str(self.inner.to_string().as_str())
let str_val = format!("{}:{:?}", self.policy_id, self.ap_table);
str_val.serialize(serializer)
}
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
//serializer.serialize_str(self.inner.to_string().as_str())
let str_val = format!("{}:{:?}", self.policy_id, self.ap_table);
str_val.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for AccessPolicyTarget {
fn deserialize<D>(deserializer: D) -> Result<AccessPolicyTarget, D::Error> where D: Deserializer<'de> {
let str_val = String::deserialize(deserializer)?;
let (policy_id, table_name) = str_val.split_once(":").ok_or_else(|| serde::de::Error::custom("AccessPolicyTarget must be in the format `access_policy_id:policy_subfield`"))?;
fn deserialize<D>(deserializer: D) -> Result<AccessPolicyTarget, D::Error>
where
D: Deserializer<'de>,
{
let str_val = String::deserialize(deserializer)?;
let (policy_id, table_name) = str_val.split_once(":").ok_or_else(|| serde::de::Error::custom("AccessPolicyTarget must be in the format `access_policy_id:policy_subfield`"))?;

// ensure that policy_id substring is a valid UUID/slugid
// todo: probably change `policy_id` field to custom type that enforces this for itself
if policy_id.len() != 22 {
return Err(serde::de::Error::custom(format!("The policy-id within the access-policy-target must be a valid slugid; for example, its length must be 22 characters. Actual length:{}", policy_id.len())));
}
let table: APTable = serde_json::from_value(serde_json::Value::String(table_name.o())).map_err(|e| serde::de::Error::custom(format!("Failed to parse valid table-name from access-policy-target:{}", e)))?;
Ok(AccessPolicyTarget::new(policy_id.o(), table))
}
// ensure that policy_id substring is a valid UUID/slugid
// todo: probably change `policy_id` field to custom type that enforces this for itself
if policy_id.len() != 22 {
return Err(serde::de::Error::custom(format!("The policy-id within the access-policy-target must be a valid slugid; for example, its length must be 22 characters. Actual length:{}", policy_id.len())));
}
let table: APTable = serde_json::from_value(serde_json::Value::String(table_name.o())).map_err(|e| serde::de::Error::custom(format!("Failed to parse valid table-name from access-policy-target:{}", e)))?;

Ok(AccessPolicyTarget::new(policy_id.o(), table))
}
}

#[Scalar]
impl ScalarType for AccessPolicyTarget {
fn parse(value: Value) -> InputValueResult<Self> {
match value {
Value::String(str_val) => {
//Ok(serde_json::from_str(&str_val).map_err(|e| InputValueError::custom(e))?)
let (policy_id, table_name) = str_val.split_once(":").ok_or_else(|| InputValueError::custom("AccessPolicyTarget must be in the format `access_policy_id:policy_subfield`"))?;
fn parse(value: Value) -> InputValueResult<Self> {
match value {
Value::String(str_val) => {
//Ok(serde_json::from_str(&str_val).map_err(|e| InputValueError::custom(e))?)
let (policy_id, table_name) = str_val.split_once(":").ok_or_else(|| InputValueError::custom("AccessPolicyTarget must be in the format `access_policy_id:policy_subfield`"))?;

// ensure that policy_id substring is a valid UUID/slugid
// todo: probably change `policy_id` field to custom type that enforces this for itself
if policy_id.len() != 22 {
return Err(InputValueError::custom(format!("The policy-id within the access-policy-target must be a valid slugid; for example, its length must be 22 characters. Actual length:{}", policy_id.len())));
}
let table: APTable = serde_json::from_value(serde_json::Value::String(table_name.o())).map_err(|e| InputValueError::custom(format!("Failed to parse valid table-name from access-policy-target:{}", e)))?;

// ensure that policy_id substring is a valid UUID/slugid
// todo: probably change `policy_id` field to custom type that enforces this for itself
if policy_id.len() != 22 {
return Err(InputValueError::custom(format!("The policy-id within the access-policy-target must be a valid slugid; for example, its length must be 22 characters. Actual length:{}", policy_id.len())));
}
let table: APTable = serde_json::from_value(serde_json::Value::String(table_name.o())).map_err(|e| InputValueError::custom(format!("Failed to parse valid table-name from access-policy-target:{}", e)))?;

Ok(AccessPolicyTarget::new(policy_id.o(), table))
},
_ => Err(InputValueError::custom("AccessPolicyTarget must be a string")),
}
}
fn to_value(&self) -> Value {
//Value::String(serde_json::to_string(&self).unwrap())
let str_val = format!("{}:{:?}", self.policy_id, self.ap_table);
Value::String(str_val)
}
}
Ok(AccessPolicyTarget::new(policy_id.o(), table))
},
_ => Err(InputValueError::custom("AccessPolicyTarget must be a string")),
}
}
fn to_value(&self) -> Value {
//Value::String(serde_json::to_string(&self).unwrap())
let str_val = format!("{}:{:?}", self.policy_id, self.ap_table);
Value::String(str_val)
}
}
Loading

0 comments on commit 15163d4

Please sign in to comment.