Skip to content

Commit

Permalink
port "build_rustdoc" to axum #51
Browse files Browse the repository at this point in the history
  • Loading branch information
secana committed Oct 15, 2023
1 parent 3a19cb2 commit 2afd0a6
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 36 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ axum-extra = { version = "0.8.0", features = ["cookie", "cookie-private"] }
tokio = { version = "1.32.0", features = ["macros"] }
tower = { version = "0.4.13", features = ["util"] }
hyper = "0.14.27"
tower-http = { version = "0.4.4", features = ["fs"] }
tower-http = { version = "0.4.4", features = ["fs", "trace"] }

[profile.release]
lto = "thin"
Expand Down
9 changes: 7 additions & 2 deletions crates/kellnr/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ async fn main() {
.route("/list_users", get(user::list_users))
.route("/login_state", get(user::login_state));

let docs = Router::new()
.route("/build", post(ui::build_rustdoc));

let app = Router::new()
.route("/version", get(ui::kellnr_version))
.route("/crates", get(ui::crates))
Expand All @@ -176,8 +179,10 @@ async fn main() {
.route("/cratesio_data", get(ui::cratesio_data))
.route("/crate", delete(ui::delete))
.nest("/user", user)
.nest("/api/v1/docs", docs)
.with_state(state)
.nest_service("/", ServeDir::new(PathBuf::from("static")));
.nest_service("/", ServeDir::new(PathBuf::from("static")))
.layer(tower_http::trace::TraceLayer::new_for_http());

axum::Server::bind(&"0.0.0.0:8000".parse().unwrap())
.serve(app.into_make_service())
Expand Down Expand Up @@ -329,7 +334,7 @@ pub fn build_rocket(
routes![
docs::api::publish_docs,
docs::api::docs_in_queue,
ui::build_rustdoc
//ui::build_rustdoc
],
)
.mount(
Expand Down
95 changes: 64 additions & 31 deletions crates/web_ui/src/ui.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
use crate::error::RouteError;
use crate::session::{AdminUser, AnyUser, MaybeUser};
use crate::session::{AdminUser, MaybeUser};
use appstate::AppState;
use common::crate_data::CrateData;
use common::crate_overview::CrateOverview;
use common::normalized_name::NormalizedName;
use common::original_name::OriginalName;
use common::version::Version;
use db::error::DbError;
use db::DbProvider;
use registry::kellnr_crate_storage::KellnrCrateStorage;
use reqwest::StatusCode;
use rocket::tokio::sync::RwLock;
use rocket::{catch, delete, http, post, Request, State};
use rocket::{catch, delete, http, Request, State};
use settings::Settings;
use tracing::error;

Expand Down Expand Up @@ -182,23 +179,31 @@ pub async fn delete(
if state.settings.git_index {
if let Err(e) = state.crate_index.delete(&name, &version).await {
error!("Failed to delete crate from index: {}", e);
return Err(RouteError::Status(axum::http::StatusCode::INTERNAL_SERVER_ERROR));
return Err(RouteError::Status(
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
));
}
}

if let Err(e) = state.db.delete_crate(&name.to_normalized(), &version).await {
error!("Failed to delete crate from database: {:?}", e);
return Err(RouteError::Status(axum::http::StatusCode::INTERNAL_SERVER_ERROR));
return Err(RouteError::Status(
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
));
}

if let Err(e) = state.crate_storage.delete(&name, &version).await {
error!("Failed to delete crate from storage: {}", e);
return Err(RouteError::Status(axum::http::StatusCode::INTERNAL_SERVER_ERROR));
return Err(RouteError::Status(
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
));
}

if let Err(e) = docs::delete(&name, &version, &state.settings).await {
error!("Failed to delete crate from docs: {}", e);
return Err(RouteError::Status(axum::http::StatusCode::INTERNAL_SERVER_ERROR));
return Err(RouteError::Status(
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
));
}

Ok(())
Expand Down Expand Up @@ -246,61 +251,89 @@ pub async fn statistic(axum::extract::State(state): AppState) -> axum::response:
})
}

#[post("/build?<package>&<version>")]
pub async fn build_rustdoc(
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct BuildParams {
package: OriginalName,
version: Version,
db: &State<Box<dyn DbProvider>>,
cs: &State<RwLock<KellnrCrateStorage>>,
user: AnyUser,
) -> Result<rocket::http::Status, http::Status> {
let normalized_name = NormalizedName::from(package);
}

pub async fn build_rustdoc(
axum::extract::Query(params): axum::extract::Query<BuildParams>,
axum::extract::State(state): AppState,
user: MaybeUser,
) -> Result<(), axum::http::StatusCode> {
let normalized_name = NormalizedName::from(params.package);
let db = state.db;
let version = params.version;

// Check if crate with the version exists.
if let Some(id) = db
.get_crate_id(&normalized_name)
.await
.map_err(|_| http::Status::InternalServerError)?
.map_err(|_| axum::http::StatusCode::INTERNAL_SERVER_ERROR)?
{
if !db
.crate_version_exists(id, &version)
.await
.map_err(|_| http::Status::InternalServerError)?
.map_err(|_|axum::http::StatusCode::INTERNAL_SERVER_ERROR)?
{
return Err(http::Status::BadRequest);
return Err(axum::http::StatusCode::BAD_REQUEST);
}
} else {
return Err(http::Status::BadRequest);
return Err(axum::http::StatusCode::BAD_REQUEST);
}

// Check if the current user is the owner of the crate
use crate::session::Name;
if !db
.is_owner(&normalized_name, &user.name())
.await
.map_err(|_| http::Status::InternalServerError)?
.map_err(|_| axum::http::StatusCode::INTERNAL_SERVER_ERROR)?
&& !db
.get_user(&user.name())
.await
.map_err(|_| http::Status::InternalServerError)?
.map_err(|_| axum::http::StatusCode::INTERNAL_SERVER_ERROR)?
.is_admin
{
return Err(http::Status::Unauthorized);
return Err( axum::http::StatusCode::UNAUTHORIZED);
}

// If the user is the owner of the crate or any admin user,
// the build operation is allowed.
let is_allowed = match user {
MaybeUser::Normal(user) => {
tracing::debug!("User {} is trying to build crate {}", user, normalized_name);
db
.is_owner(&normalized_name, &user)
.await
.map_err(|_| axum::http::StatusCode::INTERNAL_SERVER_ERROR)?
},
MaybeUser::Admin(_) => {
tracing::debug!("Admin user is trying to build crate {}", normalized_name);
true
},
};

if !is_allowed {
tracing::debug!("User is not allowed to build crate {}", normalized_name);
return Err(axum::http::StatusCode::UNAUTHORIZED);
} else {
tracing::debug!("User is allowed to build crate {}", normalized_name);
}

// Add to build queue
db.add_doc_queue(
&normalized_name,
&version,
&cs.read()
.await
&state
.crate_storage
.create_rand_doc_queue_path()
.await
.map_err(|_| http::Status::InternalServerError)?,
.map_err(|_| axum::http::StatusCode::INTERNAL_SERVER_ERROR)?,
)
.await
.map_err(|_| http::Status::InternalServerError)?;
.map_err(|_| axum::http::StatusCode::INTERNAL_SERVER_ERROR)?;

Ok(http::Status::Ok)
Ok(())
}

#[delete("/index")]
Expand Down Expand Up @@ -1144,9 +1177,9 @@ mod tests {
// crates,
// kellnr_version,
// statistic,
crate_data,
// crate_data,
build_rustdoc,
cratesio_data,
// cratesio_data,
],
)
.manage(RwLock::new(crate_storage))
Expand Down
3 changes: 1 addition & 2 deletions crates/web_ui/src/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ pub async fn list_tokens(
user: MaybeUser,
State(db): DbState,
) -> Result<Json<AuthTokenList>, RouteError> {
user.assert_normal()?;

Ok(db
.get_auth_tokens(user.name())
.await
Expand Down Expand Up @@ -156,6 +154,7 @@ pub async fn login(
state.settings.session_age_seconds as i64,
))
.same_site(axum_extra::extract::cookie::SameSite::Strict)
.path("/")
.finish(),
);

Expand Down

0 comments on commit 2afd0a6

Please sign in to comment.