Skip to content

Commit

Permalink
Rephrase cargo to metadata
Browse files Browse the repository at this point in the history
Include version information in HTML
  • Loading branch information
dormant-user committed Mar 13, 2024
1 parent bbcab88 commit 9052fd0
Show file tree
Hide file tree
Showing 16 changed files with 123 additions and 77 deletions.
10 changes: 5 additions & 5 deletions src/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ pub static IMAGE_FORMATS: [&str; 7] = ["jpeg", "jpg", "png", "gif", "bmp", "svg"
pub static SECURE_INDEX: &str = "SECURE_INDEX";

/// Struct to store the cargo information gathered at compile time using the `env!` macro.
#[derive(Debug)]
pub struct Cargo {
#[derive(Debug, Clone)]
pub struct MetaData {
pub crate_name: String,
pub manifest_dir: String,
pub authors: Vec<String>,
Expand All @@ -30,8 +30,8 @@ pub struct Cargo {
/// - [Official Docs](https://doc.rust-lang.org/cargo/reference/environment-variables.html)
/// - [GitHub Issues](https://github.com/rust-lang/cargo/issues/8251#issuecomment-631731144)
/// - [GitHub Issues](https://github.com/rust-lang/cargo/issues/11966#issue-1664748892)
pub fn build_info() -> Cargo {
let cargo = Cargo {
pub fn build_info() -> Arc<MetaData> {
let metadata = MetaData {
crate_name: env!("CARGO_CRATE_NAME").to_string(),
manifest_dir: env!("CARGO_MANIFEST_DIR").to_string(),
authors: env!("CARGO_PKG_AUTHORS").split(',').map(String::from).collect(),
Expand All @@ -45,7 +45,7 @@ pub fn build_info() -> Cargo {
pkg_version_patch: env!("CARGO_PKG_VERSION_PATCH").to_string(),
pkg_version_pre: env!("CARGO_PKG_VERSION_PRE").to_string(),
};
cargo
Arc::new(metadata)
}

/// Struct to store the session information.
Expand Down
11 changes: 6 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ mod templates;
/// }
/// ```
pub async fn start() -> io::Result<()> {
let cargo = constant::build_info();
let config = squire::startup::get_config(&cargo);
let metadata = constant::build_info();
let config = squire::startup::get_config(&metadata);

squire::startup::init_logger(config.debug, config.utc_logging, &cargo.crate_name);
println!("{}[v{}] - {}", &cargo.pkg_name, &cargo.pkg_version, &cargo.description);
squire::startup::init_logger(config.debug, config.utc_logging, &metadata.crate_name);
println!("{}[v{}] - {}", &metadata.pkg_name, &metadata.pkg_version, &metadata.description);
squire::ascii_art::random();

// Log a warning message for max payload size beyond 1 GB
Expand All @@ -60,7 +60,7 @@ pub async fn start() -> io::Result<()> {
let config_clone = config.clone();
let host = format!("{}:{}", config.media_host, config.media_port);
log::info!("{} [workers:{}] running on http://{} (Press CTRL+C to quit)",
&cargo.pkg_name, &config.workers, &host);
&metadata.pkg_name, &config.workers, &host);
let jinja = templates::environment();
let fernet = constant::fernet_object();
let session = constant::session_info();
Expand All @@ -75,6 +75,7 @@ pub async fn start() -> io::Result<()> {
.app_data(web::Data::new(jinja.clone()))
.app_data(web::Data::new(fernet.clone()))
.app_data(web::Data::new(session.clone()))
.app_data(web::Data::new(metadata.clone()))
.app_data(web::PayloadConfig::default().limit(config_clone.max_payload_size))
.wrap(squire::middleware::get_cors(config_clone.websites.clone()))
.wrap(middleware::Logger::default()) // Adds a default logger middleware to the application
Expand Down
53 changes: 34 additions & 19 deletions src/routes/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,22 @@ pub async fn login(request: HttpRequest,
/// # Arguments
///
/// * `request` - A reference to the Actix web `HttpRequest` object.
/// * `config` - Configuration data for the application.
/// * `fernet` - Fernet object to encrypt the auth payload that will be set as `session_token` cookie.
/// * `template` - Configuration container for the loaded templates.
/// * `session` - Session struct that holds the `session_mapping` and `session_tracker` to handle sessions.
/// * `metadata` - Struct containing metadata of the application.
/// * `config` - Configuration data for the application.
/// * `template` - Configuration container for the loaded templates.
///
/// # Returns
///
/// Returns an `HTTPResponse` with the cookie for `session_token` reset if available.
#[get("/logout")]
pub async fn logout(request: HttpRequest,
config: web::Data<Arc<squire::settings::Config>>,
fernet: web::Data<Arc<Fernet>>,
template: web::Data<Arc<minijinja::Environment<'static>>>,
session: web::Data<Arc<constant::Session>>) -> HttpResponse {
session: web::Data<Arc<constant::Session>>,
metadata: web::Data<Arc<constant::MetaData>>,
config: web::Data<Arc<squire::settings::Config>>,
template: web::Data<Arc<minijinja::Environment<'static>>>) -> HttpResponse {
let host = request.connection_info().host().to_owned();
let logout_template = template.get_template("logout").unwrap();
let mut response = HttpResponse::build(StatusCode::OK);
Expand All @@ -117,18 +119,22 @@ pub async fn logout(request: HttpRequest,
} else {
log::warn!("Session information for {} was not stored or no file was rendered", host);
}
rendered = logout_template.render(minijinja::context!(detail => "You have been logged out successfully.")).unwrap();
rendered = logout_template.render(minijinja::context!(
version => metadata.pkg_version,
detail => "You have been logged out successfully."
)).unwrap();

let mut cookie = Cookie::new("session_token", "");
cookie.set_same_site(SameSite::Strict);
cookie.make_removal();
response.cookie(cookie);
} else {
log::debug!("No stored session found for {}", host);
rendered = logout_template.render(
minijinja::context!(detail => "You are not logged in. Please click the button below to proceed.",
show_login => true)
).unwrap();
rendered = logout_template.render(minijinja::context!(
version => metadata.pkg_version,
detail => "You are not logged in. Please click the button below to proceed.",
show_login => true
)).unwrap();
}
// response.finish() is not required since setting the body will close the response
response.body(rendered)
Expand All @@ -139,21 +145,23 @@ pub async fn logout(request: HttpRequest,
/// # Arguments
///
/// * `request` - A reference to the Actix web `HttpRequest` object.
/// * `config` - Configuration data for the application.
/// * `fernet` - Fernet object to encrypt the auth payload that will be set as `session_token` cookie.
/// * `template` - Configuration container for the loaded templates.
/// * `session` - Session struct that holds the `session_mapping` and `session_tracker` to handle sessions.
/// * `metadata` - Struct containing metadata of the application.
/// * `config` - Configuration data for the application.
/// * `template` - Configuration container for the loaded templates.
///
/// # Returns
///
/// * `200` - Returns an `HTTPResponse` with the home/listing page if session token is valid.
/// * `401` - HttpResponse with an error message for failed authentication.
#[get("/home")]
pub async fn home(request: HttpRequest,
config: web::Data<Arc<squire::settings::Config>>,
fernet: web::Data<Arc<Fernet>>,
template: web::Data<Arc<minijinja::Environment<'static>>>,
session: web::Data<Arc<constant::Session>>) -> HttpResponse {
session: web::Data<Arc<constant::Session>>,
metadata: web::Data<Arc<constant::MetaData>>,
config: web::Data<Arc<squire::settings::Config>>,
template: web::Data<Arc<minijinja::Environment<'static>>>) -> HttpResponse {
let auth_response = squire::authenticator::verify_token(&request, &config, &fernet, &session);
if !auth_response.ok {
return failed_auth(auth_response, &config);
Expand All @@ -168,6 +176,7 @@ pub async fn home(request: HttpRequest,
.content_type("text/html; charset=utf-8")
.body(
listing.render(minijinja::context!(
version => metadata.pkg_version,
files => listing_page.files,
user => auth_response.username,
secure_index => constant::SECURE_INDEX,
Expand All @@ -181,28 +190,34 @@ pub async fn home(request: HttpRequest,
///
/// # Arguments
///
/// * `template` - Configuration container for the loaded templates.
/// * `request` - A reference to the Actix web `HttpRequest` object.
/// * `metadata` - Struct containing metadata of the application.
/// * `template` - Configuration container for the loaded templates.
///
/// # Returns
///
/// HttpResponse with either a session expiry or unauthorized message.
#[get("/error")]
pub async fn error(template: web::Data<Arc<minijinja::Environment<'static>>>,
request: HttpRequest) -> HttpResponse {
pub async fn error(request: HttpRequest,
metadata: web::Data<Arc<constant::MetaData>>,
template: web::Data<Arc<minijinja::Environment<'static>>>) -> HttpResponse {
if let Some(detail) = request.cookie("detail") {
log::info!("Error response for /error: {}", detail.value());
let session = template.get_template("session").unwrap();
return HttpResponse::build(StatusCode::UNAUTHORIZED)
.content_type("text/html; charset=utf-8")
.body(session.render(minijinja::context!(reason => detail.value())).unwrap());
.body(session.render(minijinja::context!(
version => metadata.pkg_version,
reason => detail.value()
)).unwrap());
}

log::info!("Sending unauthorized response for /error");
let error = template.get_template("error").unwrap();
HttpResponse::build(StatusCode::UNAUTHORIZED)
.content_type("text/html; charset=utf-8")
.body(error.render(minijinja::context!(
version => metadata.pkg_version,
title => "LOGIN FAILED",
description => "USER ERROR - REPLACE USER",
help => r"Forgot Password?\n\nRelax and try to remember your password.",
Expand Down
12 changes: 6 additions & 6 deletions src/routes/basics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,21 @@ pub async fn health() -> HttpResponse {
/// # Arguments
///
/// * `request` - A reference to the Actix web `HttpRequest` object.
/// * `template` - Configuration container for the loaded templates.
/// * `session` - Session struct that holds the `session_mapping` and `session_tracker` to handle sessions.
/// * `metadata` - Struct containing metadata of the application.
/// * `template` - Configuration container for the loaded templates.
///
/// # Returns
///
/// Returns an `HttpResponse` with the index page as its body.
#[get("/")]
pub async fn root(request: HttpRequest,
template: web::Data<Arc<minijinja::Environment<'static>>>,
session: web::Data<Arc<constant::Session>>) -> HttpResponse {
// Log the connection using the squire::logger::log_connection function.
session: web::Data<Arc<constant::Session>>,
metadata: web::Data<Arc<constant::MetaData>>,
template: web::Data<Arc<minijinja::Environment<'static>>>) -> HttpResponse {
squire::logger::log_connection(&request, &session);

let index = template.get_template("index").unwrap();
HttpResponse::build(StatusCode::OK)
.content_type("text/html; charset=utf-8")
.body(index.render(minijinja::context!()).unwrap()) // no arguments to render
.body(index.render(minijinja::context!(version => &metadata.pkg_version)).unwrap())
}
47 changes: 33 additions & 14 deletions src/routes/media.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use minijinja;
use serde::Deserialize;
use url::form_urlencoded;

use crate::{constant, squire, routes};
use crate::{constant, routes, squire};

/// Represents the payload structure for deserializing data from the request query parameters.
#[derive(Deserialize)]
Expand Down Expand Up @@ -75,6 +75,7 @@ fn subtitles(true_path: PathBuf, relative_path: &String) -> Subtitles {
/// * `info` - Query string from the request.
/// * `fernet` - Fernet object to encrypt the auth payload that will be set as `session_token` cookie.
/// * `session` - Session struct that holds the `session_mapping` and `session_tracker` to handle sessions.
/// * `metadata` - Struct containing metadata of the application.
/// * `config` - Configuration data for the application.
/// * `template` - Configuration container for the loaded templates.
///
Expand All @@ -86,6 +87,7 @@ pub async fn track(request: HttpRequest,
info: web::Query<Payload>,
fernet: web::Data<Arc<Fernet>>,
session: web::Data<Arc<constant::Session>>,
metadata: web::Data<Arc<constant::MetaData>>,
config: web::Data<Arc<squire::settings::Config>>,
template: web::Data<Arc<minijinja::Environment<'static>>>) -> HttpResponse {
let auth_response = squire::authenticator::verify_token(&request, &config, &fernet, &session);
Expand All @@ -95,8 +97,9 @@ pub async fn track(request: HttpRequest,
if !squire::authenticator::verify_secure_index(&PathBuf::from(&info.file), &auth_response.username) {
return squire::responses::restricted(
template.get_template("error").unwrap(),
&auth_response.username
)
&auth_response.username,
&metadata.pkg_version
);
}
squire::logger::log_connection(&request, &session);
log::debug!("{}", auth_response.detail);
Expand All @@ -108,7 +111,8 @@ pub async fn track(request: HttpRequest,
.content_type("text/plain")
.body(content),
Err(_) => squire::responses::not_found(template.get_template("error").unwrap(),
&format!("'{}' was not found", &info.file))
&format!("'{}' was not found", &info.file),
&metadata.pkg_version)
}
}

Expand Down Expand Up @@ -140,6 +144,7 @@ fn render_content(landing: minijinja::Template,
/// * `media_path` - The path parameter representing the media file or directory.
/// * `fernet` - Fernet object to encrypt the auth payload that will be set as `session_token` cookie.
/// * `session` - Session struct that holds the `session_mapping` and `session_tracker` to handle sessions.
/// * `metadata` - Struct containing metadata of the application.
/// * `config` - Configuration data for the application.
/// * `template` - Configuration container for the loaded templates.
///
Expand All @@ -151,6 +156,7 @@ pub async fn stream(request: HttpRequest,
media_path: web::Path<String>,
fernet: web::Data<Arc<Fernet>>,
session: web::Data<Arc<constant::Session>>,
metadata: web::Data<Arc<constant::MetaData>>,
config: web::Data<Arc<squire::settings::Config>>,
template: web::Data<Arc<minijinja::Environment<'static>>>) -> HttpResponse {
let auth_response = squire::authenticator::verify_token(&request, &config, &fernet, &session);
Expand All @@ -163,14 +169,18 @@ pub async fn stream(request: HttpRequest,
if !squire::authenticator::verify_secure_index(&PathBuf::from(&filepath), &auth_response.username) {
return squire::responses::restricted(
template.get_template("error").unwrap(),
&auth_response.username
)
&auth_response.username,
&metadata.pkg_version
);
}
// True path of the media file
let __target = config.media_source.join(&filepath);
if !__target.exists() {
return squire::responses::not_found(template.get_template("error").unwrap(),
&format!("'{}' was not found", filepath));
return squire::responses::not_found(
template.get_template("error").unwrap(),
&format!("'{}' was not found", filepath),
&metadata.pkg_version
);
}
// True path of the media file as a String
let __target_str = __target.to_string_lossy().to_string();
Expand All @@ -183,12 +193,13 @@ pub async fn stream(request: HttpRequest,
let next = rust_iter.next.unwrap_or_default();
let secure_index = constant::SECURE_INDEX.to_string();
let mut context_builder = vec![
("version", &metadata.pkg_version),
("media_title", &__filename),
("path", &render_path),
("previous", &prev),
("next", &next),
("user", &auth_response.username),
("secure_index", &secure_index)
("secure_index", &secure_index),
].into_iter().collect::<HashMap<_, _>>();
if constant::IMAGE_FORMATS
.contains(&render_path.split('.')
Expand Down Expand Up @@ -228,11 +239,12 @@ pub async fn stream(request: HttpRequest,
child_dir.strip_suffix(&format!("_{}", constant::SECURE_INDEX)).unwrap()
)
} else {
child_dir.clone()
child_dir
};
return HttpResponse::build(StatusCode::OK)
.content_type("text/html; charset=utf-8")
.body(listing.render(minijinja::context!(
version => metadata.pkg_version,
custom_title => custom_title,
files => listing_page.files,
user => auth_response.username,
Expand All @@ -241,7 +253,7 @@ pub async fn stream(request: HttpRequest,
secured_directories => listing_page.secured_directories
)).unwrap());
}
log::error!("Something went really wrong");
log::error!("Something went horribly wrong");
log::error!("Media Path: {}", filepath);
log::error!("Target: {}", __target_str);
HttpResponse::ExpectationFailed().json(routes::auth::DetailError {
Expand All @@ -257,6 +269,7 @@ pub async fn stream(request: HttpRequest,
/// * `info` - The query parameter containing the file information.
/// * `fernet` - Fernet object to encrypt the auth payload that will be set as `session_token` cookie.
/// * `session` - Session struct that holds the `session_mapping` and `session_tracker` to handle sessions.
/// * `metadata` - Struct containing metadata of the application.
/// * `config` - Configuration data for the application.
/// * `template` - Configuration container for the loaded templates.
///
Expand All @@ -268,6 +281,7 @@ pub async fn streaming_endpoint(request: HttpRequest,
info: web::Query<Payload>,
fernet: web::Data<Arc<Fernet>>,
session: web::Data<Arc<constant::Session>>,
metadata: web::Data<Arc<constant::MetaData>>,
config: web::Data<Arc<squire::settings::Config>>,
template: web::Data<Arc<minijinja::Environment<'static>>>) -> HttpResponse {
let auth_response = squire::authenticator::verify_token(&request, &config, &fernet, &session);
Expand All @@ -278,8 +292,9 @@ pub async fn streaming_endpoint(request: HttpRequest,
if !squire::authenticator::verify_secure_index(&media_path, &auth_response.username) {
return squire::responses::restricted(
template.get_template("error").unwrap(),
&auth_response.username
)
&auth_response.username,
&metadata.pkg_version
);
}
squire::logger::log_connection(&request, &session);
let host = request.connection_info().host().to_owned();
Expand All @@ -295,5 +310,9 @@ pub async fn streaming_endpoint(request: HttpRequest,
}
let error = format!("File {:?} not found", media_path);
log::error!("{}", error);
squire::responses::not_found(template.get_template("error").unwrap(), &error)
squire::responses::not_found(
template.get_template("error").unwrap(),
&error,
&metadata.pkg_version
)
}
Loading

0 comments on commit 9052fd0

Please sign in to comment.