- main
- manifest
- deps
- main
- Install
- Run
use anyhow::{anyhow, Result};
use fastly::http::{header, StatusCode};
use fastly::{Error, Request, Response};
use std::collections::HashSet;
const BACKEND_NAME: &str = "origin_0";
#[fastly::main]
fn main(req: Request) -> Result<Response, Error> {
log_fastly::init_simple("my_log", log::LevelFilter::Info);
match do_req_with_permission_check(req) {
Ok(resp) => Ok(resp),
Err(e) => {
log::info!("{}", e);
Ok(Response::from_status(StatusCode::FORBIDDEN))
}
}
}
fn do_req_with_permission_check(req: Request) -> Result<Response> {
let req_permission = get_req_permission(&req)?;
let resp = req.send(BACKEND_NAME)?;
let require_group = resp
.get_header("require-group")
.ok_or_else(|| anyhow!("No require-group header found in response"))?
.to_str()?;
let a_set = permissions_into_set(&req_permission);
let b_set = permissions_into_set(require_group);
let mut intersection_set = a_set.intersection(&b_set);
if intersection_set.next().is_none() {
return Err(anyhow!("No intersection in permission found"));
}
Ok(resp)
}
fn get_req_permission(req: &Request) -> Result<String> {
let cookie_val: &str = req
.get_header(header::COOKIE)
.ok_or_else(|| anyhow!("No cookie found"))?
.to_str()?;
cookie_val
.split(';')
.find_map(|kv| {
let index = kv.find('=')?;
let (key, value) = kv.split_at(index);
if key.trim() != "permission" {
return None;
}
let value = value[1..].to_string();
Some(value)
})
.ok_or_else(|| anyhow!("No permission found in cookie"))
}
fn permissions_into_set(p: &str) -> HashSet<&str> {
p.split(':').filter(|s| !s.is_empty()).collect()
}