Compare commits
	
		
			5 Commits
		
	
	
		
			current
			...
			06e1474396
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 06e1474396 | |||
|  | adb9c728f4 | ||
|  | fc02eaea4a | ||
|  | 91f87302fb | ||
|  | 97f186dc33 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -3,3 +3,5 @@ | ||||
| /venv | ||||
| .cargo | ||||
| /.idea | ||||
| web/static/index.html | ||||
| web/static/assets | ||||
|   | ||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| [submodule "reminder-dashboard"] | ||||
| 	path = reminder-dashboard | ||||
| 	url = gitea@gitea.jellypro.xyz:jude/reminder-dashboard | ||||
							
								
								
									
										26
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										26
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -2059,6 +2059,27 @@ dependencies = [ | ||||
|  "yansi", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "prometheus" | ||||
| version = "0.13.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "fnv", | ||||
|  "lazy_static", | ||||
|  "memchr", | ||||
|  "parking_lot", | ||||
|  "protobuf", | ||||
|  "thiserror", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "protobuf" | ||||
| version = "2.28.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" | ||||
|  | ||||
| [[package]] | ||||
| name = "quote" | ||||
| version = "1.0.33" | ||||
| @@ -2173,7 +2194,7 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" | ||||
|  | ||||
| [[package]] | ||||
| name = "reminder-rs" | ||||
| version = "1.6.47" | ||||
| version = "1.6.48" | ||||
| dependencies = [ | ||||
|  "base64 0.21.4", | ||||
|  "chrono", | ||||
| @@ -2201,7 +2222,7 @@ dependencies = [ | ||||
|  | ||||
| [[package]] | ||||
| name = "reminder_web" | ||||
| version = "0.1.2" | ||||
| version = "0.1.3" | ||||
| dependencies = [ | ||||
|  "base64 0.13.1", | ||||
|  "chrono", | ||||
| @@ -2210,6 +2231,7 @@ dependencies = [ | ||||
|  "lazy_static", | ||||
|  "log", | ||||
|  "oauth2", | ||||
|  "prometheus", | ||||
|  "rand", | ||||
|  "reqwest", | ||||
|  "rocket", | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| [package] | ||||
| name = "reminder-rs" | ||||
| version = "1.6.47" | ||||
| version = "1.6.48" | ||||
| authors = ["Jude Southworth <judesouthworth@pm.me>"] | ||||
| edition = "2021" | ||||
| license = "AGPL-3.0 only" | ||||
| @@ -43,6 +43,7 @@ assets = [ | ||||
|     ["conf/default.env", "etc/reminder-rs/config.env", "600"], | ||||
|     ["conf/Rocket.toml", "etc/reminder-rs/Rocket.toml", "600"], | ||||
|     ["web/static/**/*", "lib/reminder-rs/static", "644"], | ||||
|     ["reminder-dashboard/dist/static/**/*", "lib/reminder-rs/static", "644"], | ||||
|     ["web/templates/**/*", "lib/reminder-rs/templates", "644"], | ||||
|     ["healthcheck", "lib/reminder-rs/healthcheck", "755"], | ||||
|     ["cron.d/reminder_health", "etc/cron.d/reminder_health", "644"], | ||||
|   | ||||
							
								
								
									
										1
									
								
								reminder-dashboard
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								reminder-dashboard
									
									
									
									
									
										Submodule
									
								
							 Submodule reminder-dashboard added at 8ba7a39ce5
									
								
							| @@ -114,6 +114,8 @@ pub async fn offset( | ||||
|     #[description = "Number of minutes to offset by"] minutes: Option<isize>, | ||||
|     #[description = "Number of seconds to offset by"] seconds: Option<isize>, | ||||
| ) -> Result<(), Error> { | ||||
|     ctx.defer().await?; | ||||
|  | ||||
|     let combined_time = hours.map_or(0, |h| h * HOUR as isize) | ||||
|         + minutes.map_or(0, |m| m * MINUTE as isize) | ||||
|         + seconds.map_or(0, |s| s); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| [package] | ||||
| name = "reminder_web" | ||||
| version = "0.1.2" | ||||
| version = "0.1.3" | ||||
| authors = ["jellywx <judesouthworth@pm.me>"] | ||||
| edition = "2018" | ||||
|  | ||||
| @@ -19,3 +19,4 @@ lazy_static = "1.4.0" | ||||
| rand = "0.8" | ||||
| base64 = "0.13" | ||||
| csv = "1.2" | ||||
| prometheus = "0.13.3" | ||||
|   | ||||
| @@ -6,6 +6,7 @@ mod consts; | ||||
| mod macros; | ||||
| mod catchers; | ||||
| mod guards; | ||||
| mod metrics; | ||||
| mod routes; | ||||
|  | ||||
| use std::{env, path::Path}; | ||||
| @@ -25,7 +26,10 @@ use serenity::{ | ||||
| }; | ||||
| use sqlx::{MySql, Pool}; | ||||
|  | ||||
| use crate::consts::{CNC_GUILD, DISCORD_OAUTH_AUTHORIZE, DISCORD_OAUTH_TOKEN, SUBSCRIPTION_ROLES}; | ||||
| use crate::{ | ||||
|     consts::{CNC_GUILD, DISCORD_OAUTH_AUTHORIZE, DISCORD_OAUTH_TOKEN, SUBSCRIPTION_ROLES}, | ||||
|     metrics::{init_metrics, MetricProducer}, | ||||
| }; | ||||
|  | ||||
| type Database = MySql; | ||||
|  | ||||
| @@ -64,7 +68,10 @@ pub async fn initialize( | ||||
|     let static_path = | ||||
|         if Path::new("web/static").exists() { "web/static" } else { "/lib/reminder-rs/static" }; | ||||
|  | ||||
|     init_metrics(); | ||||
|  | ||||
|     rocket::build() | ||||
|         .attach(MetricProducer) | ||||
|         .attach(Template::fairing()) | ||||
|         .register( | ||||
|             "/", | ||||
| @@ -85,12 +92,13 @@ pub async fn initialize( | ||||
|         .mount( | ||||
|             "/", | ||||
|             routes![ | ||||
|                 routes::index, | ||||
|                 routes::cookies, | ||||
|                 routes::index, | ||||
|                 routes::metrics::metrics, | ||||
|                 routes::privacy, | ||||
|                 routes::terms, | ||||
|                 routes::return_to_same_site, | ||||
|                 routes::report::report_error, | ||||
|                 routes::return_to_same_site, | ||||
|                 routes::terms, | ||||
|             ], | ||||
|         ) | ||||
|         .mount( | ||||
|   | ||||
							
								
								
									
										43
									
								
								web/src/metrics.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								web/src/metrics.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| use lazy_static::lazy_static; | ||||
| use prometheus::{IntCounterVec, Opts, Registry}; | ||||
| use rocket::{ | ||||
|     fairing::{Fairing, Info, Kind}, | ||||
|     Data, Request, Response, | ||||
| }; | ||||
|  | ||||
| lazy_static! { | ||||
|     pub static ref REGISTRY: Registry = Registry::new(); | ||||
|     static ref REQUEST_COUNTER: IntCounterVec = | ||||
|         IntCounterVec::new(Opts::new("requests", "Requests"), &["method", "route"]).unwrap(); | ||||
|     static ref RESPONSE_COUNTER: IntCounterVec = | ||||
|         IntCounterVec::new(Opts::new("responses", "Responses"), &["status", "route"]).unwrap(); | ||||
| } | ||||
|  | ||||
| pub fn init_metrics() { | ||||
|     REGISTRY.register(Box::new(REQUEST_COUNTER.clone())).unwrap(); | ||||
| } | ||||
|  | ||||
| pub struct MetricProducer; | ||||
|  | ||||
| #[rocket::async_trait] | ||||
| impl Fairing for MetricProducer { | ||||
|     fn info(&self) -> Info { | ||||
|         Info { name: "Metrics fairing", kind: Kind::Request } | ||||
|     } | ||||
|  | ||||
|     async fn on_request(&self, req: &mut Request<'_>, _data: &mut Data<'_>) { | ||||
|         if let Some(route) = req.route() { | ||||
|             REQUEST_COUNTER | ||||
|                 .with_label_values(&[req.method().as_str(), &route.uri.to_string()]) | ||||
|                 .inc(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     async fn on_response<'r>(&self, req: &'r Request<'_>, resp: &mut Response<'r>) { | ||||
|         if let Some(route) = req.route() { | ||||
|             RESPONSE_COUNTER | ||||
|                 .with_label_values(&[&resp.status().code.to_string(), &route.uri.to_string()]) | ||||
|                 .inc(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1 +0,0 @@ | ||||
|  | ||||
| @@ -1,9 +1,13 @@ | ||||
| use std::collections::HashMap; | ||||
| use std::path::Path; | ||||
|  | ||||
| use chrono::{naive::NaiveDateTime, Utc}; | ||||
| use rand::{rngs::OsRng, seq::IteratorRandom}; | ||||
| use rocket::{http::CookieJar, response::Redirect, serde::json::json}; | ||||
| use rocket_dyn_templates::Template; | ||||
| use rocket::{ | ||||
|     fs::{relative, NamedFile}, | ||||
|     http::CookieJar, | ||||
|     response::Redirect, | ||||
|     serde::json::json, | ||||
| }; | ||||
| use serde::{Deserialize, Deserializer, Serialize}; | ||||
| use serenity::{ | ||||
|     client::Context, | ||||
| @@ -27,7 +31,6 @@ use crate::{ | ||||
|  | ||||
| pub mod api; | ||||
| pub mod export; | ||||
| pub mod guild; | ||||
|  | ||||
| type Unset<T> = Option<T>; | ||||
|  | ||||
| @@ -657,22 +660,26 @@ async fn create_database_channel( | ||||
| } | ||||
|  | ||||
| #[get("/")] | ||||
| pub async fn dashboard_home(cookies: &CookieJar<'_>) -> Result<Template, Redirect> { | ||||
| pub async fn dashboard_home(cookies: &CookieJar<'_>) -> Result<NamedFile, Redirect> { | ||||
|     if cookies.get_private("userid").is_some() { | ||||
|         let mut map = HashMap::new(); | ||||
|         map.insert("version", env!("CARGO_PKG_VERSION")); | ||||
|         Ok(Template::render("dashboard", &map)) | ||||
|         NamedFile::open(Path::new(relative!("static/index.html"))).await.map_err(|e| { | ||||
|             warn!("Couldn't render dashboard: {:?}", e); | ||||
|  | ||||
|             Redirect::to("/login/discord") | ||||
|         }) | ||||
|     } else { | ||||
|         Err(Redirect::to("/login/discord")) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[get("/<_..>")] | ||||
| pub async fn dashboard(cookies: &CookieJar<'_>) -> Result<Template, Redirect> { | ||||
| pub async fn dashboard(cookies: &CookieJar<'_>) -> Result<NamedFile, Redirect> { | ||||
|     if cookies.get_private("userid").is_some() { | ||||
|         let mut map = HashMap::new(); | ||||
|         map.insert("version", env!("CARGO_PKG_VERSION")); | ||||
|         Ok(Template::render("dashboard", &map)) | ||||
|         NamedFile::open(Path::new(relative!("static/index.html"))).await.map_err(|e| { | ||||
|             warn!("Couldn't render dashboard: {:?}", e); | ||||
|  | ||||
|             Redirect::to("/login/discord") | ||||
|         }) | ||||
|     } else { | ||||
|         Err(Redirect::to("/login/discord")) | ||||
|     } | ||||
|   | ||||
							
								
								
									
										18
									
								
								web/src/routes/metrics.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								web/src/routes/metrics.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| use prometheus; | ||||
|  | ||||
| use crate::metrics::REGISTRY; | ||||
|  | ||||
| #[get("/metrics")] | ||||
| pub async fn metrics() -> String { | ||||
|     let encoder = prometheus::TextEncoder::new(); | ||||
|     let res_custom = encoder.encode_to_string(®ISTRY.gather()); | ||||
|  | ||||
|     match res_custom { | ||||
|         Ok(s) => s, | ||||
|         Err(e) => { | ||||
|             warn!("Error encoding metrics: {:?}", e); | ||||
|  | ||||
|             String::new() | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| pub mod admin; | ||||
| pub mod dashboard; | ||||
| pub mod login; | ||||
| pub mod metrics; | ||||
| pub mod report; | ||||
|  | ||||
| use std::collections::HashMap; | ||||
|   | ||||
| @@ -218,17 +218,16 @@ div.inset-content { | ||||
|     margin-right: 10%; | ||||
| } | ||||
|  | ||||
| div.flash-message { | ||||
| div.flash-container { | ||||
|     position: fixed; | ||||
|     width: 100%; | ||||
|     bottom: 0; | ||||
| } | ||||
|  | ||||
| div.flash-message { | ||||
|     width: calc(100% - 32px); | ||||
|     margin: 16px !important; | ||||
|     z-index: 99; | ||||
|     bottom: 0; | ||||
|     display: none; | ||||
| } | ||||
|  | ||||
| div.flash-message.is-active { | ||||
|     display: block; | ||||
| } | ||||
|  | ||||
| body { | ||||
| @@ -633,6 +632,10 @@ li.highlight { | ||||
|     display: flex; | ||||
| } | ||||
|  | ||||
| .button-row-edit > button { | ||||
|     margin-right: 4px; | ||||
| } | ||||
|  | ||||
| .button-row .button-row-reminder { | ||||
|     flex-grow: 0; | ||||
|     padding: 2px; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user