1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
extern crate proc_macro; use proc_macro::TokenStream; use proc_macro2::{Ident, Span}; use quote::quote; use syn::{ parse_macro_input, FnArg, ItemFn, Pat }; #[proc_macro_attribute] pub fn login_required(_: TokenStream, func: TokenStream) -> TokenStream { let func = parse_macro_input!(func as ItemFn); let func_vis = &func.vis; let func_block = &func.block; let login_ident = Ident::new("_id", Span::call_site()); let func_sig = &func.sig; let func_name = &func_sig.ident; let func_generics = &func_sig.generics; let func_inputs = &func_sig.inputs; let func_output = &func_sig.output; let func_async = &func_sig.asyncness.unwrap(); let identity_vec: Vec<_> = func_inputs .iter() .filter(|s| match s { FnArg::Typed(ref arg_type) => { if let Pat::Ident(ref id) = *arg_type.pat { id.ident.eq(&login_ident) } else { false } } _ => unreachable!("This not gonna happend!"), }) .map(|s| match s { FnArg::Typed(ref arg) => &arg.pat, _ => unreachable!("This not gonna happend!"), }) .collect(); let identity = *identity_vec.get(0).unwrap(); let expended = quote! { #func_vis #func_async fn #func_name #func_generics(#func_inputs) #func_output { if let Some(ident) = #identity.identity() { #func_block } else { actix_web::HttpResponse::Unauthorized().json("Unauthorized") } } }; expended.into() }