feat: write auth ics proxy

This commit is contained in:
newt 2024-09-25 01:09:28 +01:00
commit 4b70ac331d
4 changed files with 1662 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

1574
Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

12
Cargo.toml Normal file
View file

@ -0,0 +1,12 @@
[package]
name = "uofgcal"
version = "0.1.0"
edition = "2021"
[dependencies]
axum = "0.7.6"
color-eyre = "0.6.3"
futures = "0.3.30"
reqwest = "0.12.7"
serde = { version = "1.0.210", features = ["derive"] }
tokio = { version = "1.40.0", features = ["full"] }

75
src/main.rs Normal file
View file

@ -0,0 +1,75 @@
use axum::{
body::Bytes,
extract::{Query, State},
http::StatusCode,
response::{AppendHeaders, IntoResponse},
routing::get,
Router,
};
use color_eyre::Result;
use reqwest::{header, Client};
use serde::Deserialize;
use std::borrow::Cow;
use tokio::net::TcpListener;
const PORT: u16 = 8080;
#[derive(Deserialize)]
struct CalendarPayload {
calendar: Cow<'static, str>,
filename: Option<Cow<'static, str>>,
username: Cow<'static, str>,
password: Cow<'static, str>,
}
async fn get_calender(
Query(auth): Query<CalendarPayload>,
State(client): State<Client>,
) -> impl IntoResponse {
if let Ok(resp) = client
.get(auth.calendar.as_ref())
.basic_auth(auth.username.as_ref(), Some(auth.password.as_ref()))
.send()
.await
{
Ok((
AppendHeaders([
(
header::CONTENT_TYPE,
"text/calendar; charset=utf-8".to_string(),
),
(
header::CONTENT_DISPOSITION,
format!(
r#"attachment; filename="{}""#,
auth.filename.unwrap_or_else(|| {
if auth.calendar.ends_with(".ics") {
Cow::Borrowed(&auth.calendar.split('/').last().unwrap())
} else {
Cow::Borrowed("calendar.ics")
}
})
),
),
]),
resp.bytes().await.ok().unwrap_or_default(),
))
} else {
Err((
StatusCode::INTERNAL_SERVER_ERROR,
"Failed to fetch calendar".to_string(),
))
}
}
#[tokio::main]
async fn main() -> Result<()> {
color_eyre::install()?;
let tcp_listener = TcpListener::bind(format!("0.0.0.0:{PORT}")).await?;
let client = Client::new();
let router = Router::new()
.route("/", get(get_calender))
.with_state(client);
axum::serve(tcp_listener, router).await?;
Ok(())
}