use super::feature::Feature;
use super::layout::Uses;
use crate::ApiAccess;
use crate::generator::param_type;
use crate::schema::Column;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Caller {
pub access: ApiAccess,
pub user: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Extraction {
pub extractor: &'static str,
pub binding: &'static str,
pub arg: Option<&'static str>,
}
impl Caller {
pub fn extraction(self) -> Option<Extraction> {
let (extractor, binding, arg) = match (self.access, self.user) {
(ApiAccess::Public, _) => return None,
(ApiAccess::Admin, true) => ("AdminUser", "admin", Some("admin.0")),
(ApiAccess::Admin, false) => ("AdminUser", "_", None),
(_, true) => ("AuthUser", "user", Some("user")),
(_, false) => ("AuthUser", "_", None),
};
Some(Extraction {
extractor,
binding,
arg,
})
}
}
pub struct HandlerScope {
pub params: Vec<String>,
pub args: Vec<String>,
}
pub fn handler(
feature: &Feature<'_>,
uses: &mut Uses,
tenant: Option<&Column>,
caller: Caller,
) -> HandlerScope {
let mut params = Vec::new();
let mut args = Vec::new();
if let Some(Extraction {
extractor,
binding,
arg,
}) = caller.extraction()
{
uses.add(&format!("crate::shared::auth::{extractor}"));
params.push(format!("{binding}: {extractor}"));
args.extend(arg.map(str::to_owned));
}
if let Some(tenant) = tenant {
uses.add("crate::shared::tenant::Tenant");
import_type(feature, uses, tenant);
params.push(format!("tenant: Tenant<{}>", tenant.value_type()));
args.insert(0, "tenant.into_inner()".to_owned());
}
HandlerScope { params, args }
}
pub fn import_type(feature: &Feature<'_>, uses: &mut Uses, column: &Column) {
if let Some(id) = &column.typed_id {
if id.module == feature.module() {
uses.add(&format!("super::model::{}", id.name));
} else {
uses.add(&format!(
"{}::{}::models::{}",
feature.db_path, id.module, id.name
));
}
}
}
pub fn tenant_arg(table: &crate::schema::Table) -> String {
match table.tenant() {
Some(tenant) if param_type(tenant).starts_with('&') => "&tenant, ".to_owned(),
Some(_) => "tenant, ".to_owned(),
None => String::new(),
}
}