diff --git a/Cargo.toml b/Cargo.toml index 2b1f2074..7ee44161 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,2 @@ [workspace] -members = ["crates/cloud", "crates/cli", "crates/api", "crates/api-common", "crates/cloud-common", "crates/migrate"] +members = ["crates/cloud", "crates/cli", "crates/api", "crates/api-common", "crates/cloud-common", "crates/migrate", "crates/macros"] diff --git a/crates/cloud/Cargo.toml b/crates/cloud/Cargo.toml index 212fdcb6..8389cadf 100644 --- a/crates/cloud/Cargo.toml +++ b/crates/cloud/Cargo.toml @@ -44,3 +44,4 @@ aws-sdk-s3 = "0.31.2" aws-credential-types = "0.56.1" aws-config = "0.56.1" nonempty = "0.9.0" +netsblox-macros = { path = "../macros", version = "1.0.0" } diff --git a/crates/cloud/src/auth/groups.rs b/crates/cloud/src/auth/groups.rs index 004bef6a..51daba73 100644 --- a/crates/cloud/src/auth/groups.rs +++ b/crates/cloud/src/auth/groups.rs @@ -2,15 +2,30 @@ use crate::{app_data::AppData, errors::InternalError, utils}; use actix_web::HttpRequest; use mongodb::bson::doc; use netsblox_cloud_common::api; +use netsblox_macros::Witness; use crate::errors::UserError; // Permissions on groups +#[derive(Witness)] pub(crate) struct ViewGroup { pub(crate) id: api::GroupId, + // TODO: can the Witness macro add the following field? _private: (), } +// TODO: the macro, Witness, should generate this +impl ViewGroup { + fn new(id: api::GroupId) -> Self { + Self { id, _private: () } + } + + #[cfg(test)] + pub(crate) fn mock(id: api::GroupId) -> Self { + Self::new(id) + } +} + pub(crate) struct EditGroup { pub(crate) id: api::GroupId, _private: (), @@ -30,10 +45,7 @@ pub(crate) async fn try_view_group( // for now you can only view the group if you are allowed to edit it try_edit_group(app, req, group_id) .await - .map(|eg| ViewGroup { - id: eg.id, - _private: (), - }) + .map(|eg| ViewGroup::new(eg.id)) } pub(crate) async fn try_edit_group( diff --git a/crates/cloud/src/auth/hosts.rs b/crates/cloud/src/auth/hosts.rs index 00cd682d..f646f343 100644 --- a/crates/cloud/src/auth/hosts.rs +++ b/crates/cloud/src/auth/hosts.rs @@ -2,7 +2,9 @@ use super::is_super_user; use crate::app_data::AppData; use crate::errors::UserError; use actix_web::HttpRequest; +use netsblox_macros::Witness; +#[derive(Witness)] // FIXME: this doesn't work pub(crate) struct ViewAuthHosts { _private: (), } diff --git a/crates/macros/Cargo.toml b/crates/macros/Cargo.toml new file mode 100644 index 00000000..cc088469 --- /dev/null +++ b/crates/macros/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "netsblox-macros" +version = "1.0.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +proc-macro = true + +[dependencies] +quote = "1.0.35" +syn = "2.0.48" diff --git a/crates/macros/src/lib.rs b/crates/macros/src/lib.rs new file mode 100644 index 00000000..0b87175b --- /dev/null +++ b/crates/macros/src/lib.rs @@ -0,0 +1,41 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, DeriveInput}; + +#[proc_macro_derive(Witness)] +pub fn derive_witness(input: TokenStream) -> TokenStream { + let DeriveInput { ident, attrs, .. } = parse_macro_input!(input); + // TODO: add _private field to struct + let output = quote! { + impl #ident { + // "new" shouldn't be pub(crate) so it can only be instantiated in the defining file/module + // as a bonus, this would disallow anyone from trying to define a new "new" function for a Witness (already defined!) + fn new() -> Self { + todo!(); + } + + #[cfg(test)] + pub(crate) fn test( + // Figure out the attributes and make equivalent arguments here + ) -> Self { + // TODO: get the inputs and pass them through + Self { + _private: () + } + } + } + }; + + output.into() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +}