diff --git a/crates/server/.env.toml b/crates/server/.env.toml index 5d2264fa6f..931f7c4df2 100644 --- a/crates/server/.env.toml +++ b/crates/server/.env.toml @@ -5,6 +5,7 @@ HTTP_PORT = 8080 DATABASE_URL = "postgres://postgres@localhost/zed" SESSION_SECRET = "6E1GS6IQNOLIBKWMEVWF1AFO4H78KNU8" +API_TOKEN = "secret" # Available at https://github.com/organizations/zed-industries/settings/apps/zed-local-development GITHUB_APP_ID = 115633 diff --git a/crates/server/src/api.rs b/crates/server/src/api.rs new file mode 100644 index 0000000000..e9384c1f84 --- /dev/null +++ b/crates/server/src/api.rs @@ -0,0 +1,43 @@ +use crate::{AppState, Request, RequestExt as _}; +use async_trait::async_trait; +use std::sync::Arc; + +pub fn add_routes(app: &mut tide::Server>) { + app.at("/users/:github_login").get(get_user); +} + +async fn get_user(request: Request) -> tide::Result { + request.require_token().await?; + + let user = request + .db() + .get_user_by_github_login(request.param("github_login")?) + .await? + .ok_or_else(|| surf::Error::from_str(404, "user not found"))?; + + Ok(tide::Response::builder(200) + .body(tide::Body::from_json(&user)?) + .build()) +} + +#[async_trait] +pub trait RequestExt { + async fn require_token(&self) -> tide::Result<()>; +} + +#[async_trait] +impl RequestExt for Request { + async fn require_token(&self) -> tide::Result<()> { + let token = self + .header("Authorization") + .and_then(|header| header.get(0)) + .and_then(|header| header.as_str().strip_prefix("token ")) + .ok_or_else(|| surf::Error::from_str(403, "invalid authorization header"))?; + + if token == self.state().config.api_token { + Ok(()) + } else { + Err(tide::Error::from_str(403, "invalid authorization token")) + } + } +} diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs index 82c5e01c44..0f4bddc216 100644 --- a/crates/server/src/main.rs +++ b/crates/server/src/main.rs @@ -1,4 +1,5 @@ mod admin; +mod api; mod assets; mod auth; mod community; @@ -43,6 +44,7 @@ pub struct Config { pub github_client_id: String, pub github_client_secret: String, pub github_private_key: String, + pub api_token: String, } pub struct AppState { @@ -173,6 +175,7 @@ pub async fn run_server( .with_same_site_policy(SameSite::Lax), // Required obtain our session in /auth_callback ); web.with(errors::Middleware); + api::add_routes(&mut web); home::add_routes(&mut web); team::add_routes(&mut web); releases::add_routes(&mut web);