Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Add /metrics endpoint for Prometheus #471

Add /metrics endpoint for Prometheus

Add /metrics endpoint for Prometheus #471

Triggered via push October 6, 2023 20:37
Status Success
Total duration 23s
Artifacts
This run and associated checks have been archived and are scheduled for deletion. Learn more about checks retention

security.yml

on: push
security_audit
15s
security_audit
Fit to window
Zoom out
Zoom in

Annotations

3 errors and 25 warnings
&-masking with zero: /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bitflags-1.3.2/src/lib.rs#L464
error: &-masking with zero --> src/models/users.rs:14:1 | 14 | / bitflags::bitflags! { 15 | | #[derive(Serialize, Deserialize)] 16 | | #[serde(transparent)] 17 | | pub struct Badges: u64 { ... | 29 | | } 30 | | } | |_^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask = note: this error originates in the macro `__impl_bitflags` which comes from the expansion of the macro `bitflags::bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
&-masking with zero: /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bitflags-1.3.2/src/lib.rs#L464
error: &-masking with zero --> src/models/teams.rs:79:1 | 79 | / bitflags::bitflags! { 80 | | #[derive(Serialize, Deserialize)] 81 | | #[serde(transparent)] 82 | | pub struct OrganizationPermissions: u64 { ... | 94 | | } 95 | | } | |_^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask = note: this error originates in the macro `__impl_bitflags` which comes from the expansion of the macro `bitflags::bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
&-masking with zero: /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bitflags-1.3.2/src/lib.rs#L464
error: &-masking with zero --> src/models/pats.rs:12:1 | 12 | / bitflags::bitflags! { 13 | | #[derive(Serialize, Deserialize)] 14 | | #[serde(transparent)] 15 | | pub struct Scopes: u64 { ... | 107 | | } 108 | | } | |_^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask = note: `#[deny(clippy::bad_bit_mask)]` on by default = note: this error originates in the macro `__impl_bitflags` which comes from the expansion of the macro `bitflags::bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
security_audit
The following actions uses node12 which is deprecated and will be forced to run on node16: actions-rs/audit-check@v1. For more info: https://github.blog/changelog/2023-06-13-github-actions-all-actions-will-run-on-node16-instead-of-node12-by-default/
security_audit
3 warnings found!
security_audit
Unknown warning kind unsound found, please, file a bug
security_audit
Unknown warning kind unsound found, please, file a bug
you should consider adding a `Default` implementation for `Scheduler`: src/scheduler.rs#L9
warning: you should consider adding a `Default` implementation for `Scheduler` --> src/scheduler.rs:9:5 | 9 | / pub fn new() -> Self { 10 | | Scheduler { 11 | | arbiter: Arbiter::new(), 12 | | } 13 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default help: try adding this | 8 + impl Default for Scheduler { 9 + fn default() -> Self { 10 + Self::new() 11 + } 12 + } |
you should consider adding a `Default` implementation for `MemoryStore`: src/ratelimit/memory.rs#L27
warning: you should consider adding a `Default` implementation for `MemoryStore` --> src/ratelimit/memory.rs:27:5 | 27 | / pub fn new() -> Self { 28 | | debug!("Creating new MemoryStore"); 29 | | MemoryStore { 30 | | inner: Arc::new(DashMap::<String, (usize, Duration)>::new()), 31 | | } 32 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default help: try adding this | 18 + impl Default for MemoryStore { 19 + fn default() -> Self { 20 + Self::new() 21 + } 22 + } |
you should consider adding a `Default` implementation for `AuthQueue`: src/queue/session.rs#L18
warning: you should consider adding a `Default` implementation for `AuthQueue` --> src/queue/session.rs:18:5 | 18 | / pub fn new() -> Self { 19 | | AuthQueue { 20 | | session_queue: Mutex::new(HashMap::with_capacity(1000)), 21 | | pat_queue: Mutex::new(HashSet::with_capacity(1000)), 22 | | } 23 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default help: try adding this | 17 + impl Default for AuthQueue { 18 + fn default() -> Self { 19 + Self::new() 20 + } 21 + } |
you should consider adding a `Default` implementation for `PayoutsQueue`: src/queue/payouts.rs#L43
warning: you should consider adding a `Default` implementation for `PayoutsQueue` --> src/queue/payouts.rs:43:5 | 43 | / pub fn new() -> Self { 44 | | PayoutsQueue { 45 | | credential: Default::default(), 46 | | credential_expires: Utc::now() - Duration::days(30), 47 | | } 48 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default help: try adding this | 42 + impl Default for PayoutsQueue { 43 + fn default() -> Self { 44 + Self::new() 45 + } 46 + } |
you should consider adding a `Default` implementation for `DownloadQueue`: src/queue/download.rs#L11
warning: you should consider adding a `Default` implementation for `DownloadQueue` --> src/queue/download.rs:11:5 | 11 | / pub fn new() -> Self { 12 | | DownloadQueue { 13 | | queue: Mutex::new(Vec::with_capacity(1000)), 14 | | } 15 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default help: try adding this | 10 + impl Default for DownloadQueue { 11 + fn default() -> Self { 12 + Self::new() 13 + } 14 + } |
you should consider adding a `Default` implementation for `AnalyticsQueue`: src/queue/analytics.rs#L12
warning: you should consider adding a `Default` implementation for `AnalyticsQueue` --> src/queue/analytics.rs:12:5 | 12 | / pub fn new() -> Self { 13 | | AnalyticsQueue { 14 | | views_queue: DashSet::with_capacity(1000), 15 | | downloads_queue: DashSet::with_capacity(1000), 16 | | playtime_queue: DashSet::with_capacity(1000), 17 | | } 18 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default help: try adding this | 11 + impl Default for AnalyticsQueue { 12 + fn default() -> Self { 13 + Self::new() 14 + } 15 + } |
method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`: src/models/threads.rs#L81
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str` --> src/models/threads.rs:81:5 | 81 | / pub fn from_str(string: &str) -> ThreadType { 82 | | match string { 83 | | "report" => ThreadType::Report, 84 | | "project" => ThreadType::Project, ... | 87 | | } 88 | | } | |_____^ | = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait
method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`: src/models/projects.rs#L756
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str` --> src/models/projects.rs:756:5 | 756 | / pub fn from_str(string: &str) -> FileType { 757 | | match string { 758 | | "required-resource-pack" => FileType::RequiredResourcePack, 759 | | "optional-resource-pack" => FileType::OptionalResourcePack, ... | 762 | | } 763 | | } | |_____^ | = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait
method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`: src/models/projects.rs#L721
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str` --> src/models/projects.rs:721:5 | 721 | / pub fn from_str(string: &str) -> DependencyType { 722 | | match string { 723 | | "required" => DependencyType::Required, 724 | | "optional" => DependencyType::Optional, ... | 728 | | } 729 | | } | |_____^ | = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait
method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`: src/models/projects.rs#L573
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str` --> src/models/projects.rs:573:5 | 573 | / pub fn from_str(string: &str) -> VersionStatus { 574 | | match string { 575 | | "listed" => VersionStatus::Listed, 576 | | "draft" => VersionStatus::Draft, ... | 580 | | } 581 | | } | |_____^ | = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait
method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`: src/models/projects.rs#L436
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str` --> src/models/projects.rs:436:5 | 436 | / pub fn from_str(string: &str) -> MonetizationStatus { 437 | | match string { 438 | | "force-demonetized" => MonetizationStatus::ForceDemonetized, 439 | | "demonetized" => MonetizationStatus::Demonetized, ... | 442 | | } 443 | | } | |_____^ | = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait
method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`: src/models/projects.rs#L311
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str` --> src/models/projects.rs:311:5 | 311 | / pub fn from_str(string: &str) -> ProjectStatus { 312 | | match string { 313 | | "processing" => ProjectStatus::Processing, 314 | | "rejected" => ProjectStatus::Rejected, ... | 322 | | } 323 | | } | |_____^ | = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait
method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`: src/models/projects.rs#L250
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str` --> src/models/projects.rs:250:5 | 250 | / pub fn from_str(string: &str) -> SideType { 251 | | match string { 252 | | "required" => SideType::Required, 253 | | "optional" => SideType::Optional, ... | 256 | | } 257 | | } | |_____^ | = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait
method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`: src/models/collections.rs#L83
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str` --> src/models/collections.rs:83:5 | 83 | / pub fn from_str(string: &str) -> CollectionStatus { 84 | | match string { 85 | | "listed" => CollectionStatus::Listed, 86 | | "unlisted" => CollectionStatus::Unlisted, ... | 90 | | } 91 | | } | |_____^ | = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait = note: `#[warn(clippy::should_implement_trait)]` on by default
you should consider adding a `Default` implementation for `MockHost`: src/file_hosting/mock.rs#L10
warning: you should consider adding a `Default` implementation for `MockHost` --> src/file_hosting/mock.rs:10:5 | 10 | / pub fn new() -> Self { 11 | | MockHost(()) 12 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default = note: `#[warn(clippy::new_without_default)]` on by default help: try adding this | 9 + impl Default for MockHost { 10 + fn default() -> Self { 11 + Self::new() 12 + } 13 + } |
this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice`: src/database/models/user_item.rs#L355
warning: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice` --> src/database/models/user_item.rs:355:35 | 355 | .delete_many(user_ids.into_iter().flat_map(|(id, username)| { | ^^^^^^^^^ help: call directly: `iter` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref = note: `#[warn(clippy::into_iter_on_ref)]` on by default
called `unwrap` on `projects` after checking its variant with `is_some`: src/clickhouse/fetch.rs#L237
warning: called `unwrap` on `projects` after checking its variant with `is_some` --> src/clickhouse/fetch.rs:237:28 | 236 | if projects.is_some() { | --------------------- help: try: `if let Some(..) = projects` 237 | query = query.bind(projects.unwrap().iter().map(|x| x.0).collect::<Vec<_>>()); | ^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap
called `unwrap` on `projects` after checking its variant with `is_some`: src/clickhouse/fetch.rs#L174
warning: called `unwrap` on `projects` after checking its variant with `is_some` --> src/clickhouse/fetch.rs:174:28 | 173 | if projects.is_some() { | --------------------- help: try: `if let Some(..) = projects` 174 | query = query.bind(projects.unwrap().iter().map(|x| x.0).collect::<Vec<_>>()); | ^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap
called `unwrap` on `projects` after checking its variant with `is_some`: src/clickhouse/fetch.rs#L127
warning: called `unwrap` on `projects` after checking its variant with `is_some` --> src/clickhouse/fetch.rs:127:28 | 126 | if projects.is_some() { | --------------------- help: try: `if let Some(..) = projects` 127 | query = query.bind(projects.unwrap().iter().map(|x| x.0).collect::<Vec<_>>()); | ^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap
called `unwrap` on `projects` after checking its variant with `is_some`: src/clickhouse/fetch.rs#L80
warning: called `unwrap` on `projects` after checking its variant with `is_some` --> src/clickhouse/fetch.rs:80:28 | 79 | if projects.is_some() { | --------------------- help: try: `if let Some(..) = projects` 80 | query = query.bind(projects.unwrap().iter().map(|x| x.0).collect::<Vec<_>>()); | ^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap = note: `#[warn(clippy::unnecessary_unwrap)]` on by default
try not to call a closure in the expression where it is declared: src/auth/flows.rs#L1016
warning: try not to call a closure in the expression where it is declared --> src/auth/flows.rs:1016:58 | 1016 | let res: Result<HttpResponse, AuthenticationError> = (|| async move { | __________________________________________________________^ 1017 | | 1018 | | let flow = Flow::get(&state, &redis).await?; 1019 | | ... | 1177 | | } 1178 | | })().await; | |________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call = note: `#[warn(clippy::redundant_closure_call)]` on by default help: try doing something like | 1016 ~ let res: Result<HttpResponse, AuthenticationError> = async async move { 1017 + 1018 + let flow = Flow::get(&state, &redis).await?; 1019 + 1020 + // Extract cookie header from request 1021 + if let Some(Flow::OAuth { 1022 + user_id, 1023 + provider, 1024 + url, 1025 + }) = flow 1026 + { 1027 + Flow::remove(&state, &redis).await?; 1028 + 1029 + let token = provider.get_token(query).await?; 1030 + let oauth_user = provider.get_user(&token).await?; 1031 + 1032 + let user_id_opt = provider.get_user_id(&oauth_user.id, &**client).await?; 1033 + 1034 + let mut transaction = client.begin().await?; 1035 + if let Some(id) = user_id { 1036 + if user_id_opt.is_some() { 1037 + return Err(AuthenticationError::DuplicateUser); 1038 + } 1039 + 1040 + provider 1041 + .update_user_id(id, Some(&oauth_user.id), &mut transaction) 1042 + .await?; 1043 + 1044 + let user = crate::database::models::User::get_id(id, &**client, &redis).await?; 1045 + if let Some(email) = user.and_then(|x| x.email) { 1046 + send_email( 1047 + email, 1048 + "Authentication method added", 1049 + &format!("When logging into Modrinth, you can now log in using the {} authentication provider.", provider.as_str()), 1050 + "If you did not make this change, please contact us immediately through our support channels on Discord or via email ([email protected]).", 1051 + None, 1052 + )?; 1053 + } 1054 + 1055 + crate::database::models::User::clear_caches(&[(id, None)], &redis).await?; 1056 + transaction.commit().await?; 1057 + 1058 + if let Some(url) = url { 1059 + Ok(HttpResponse::TemporaryRedirect() 1060 + .append_header(("Location", &*url)) 1061 + .json(serde_json::json!({ "url": url }))) 1062 + } else { 1063 + Err(AuthenticationError::InvalidCredentials) 1064 + } 1065 + } else { 1066 + let user_id = if let Some(user_id) = user_id_opt { 1067 + let user = crate::database::models::User::get_id(user_id, &**client, &redis) 1068 + .await? 1069 + .ok_or_else(|| AuthenticationError::InvalidCredentials)?; 1070 + 1071 + if user.totp_secret.is_some() { 1072 + let flow = Flow::Login2FA { user_id: user.id } 1073 + .insert(Duration::minutes(30), &redis) 1074 + .await?; 1075 + 1076 + if let Some(url) = url { 1077 + let redirect_url = format!( 1078 + "{}{}error=2fa_required&flow={}", 1079 + url, 1080 + if url.contains('?') { "&" } else { "?" }, 1081 + flow 1082 + ); 1083 + 1084 + return Ok(HttpResponse::TemporaryRedirect() 1085 + .append_header(("Location", &*redirect_url)) 1086 + .json(serde_json::json!({ "url": redirect_url }))); 1087 + } else { 1088 + let mut ws_conn = { 1089 + let db = sockets.read().await; 1090 + 1091 + let mut x = db 1092 + .auth_sockets 1093 + .get_mut(&state) 1094 + .ok_or_else(|| AuthenticationError::SocketError)?; 1095 + 1096 + x.value_mut().clone() 1097 + }; 1098 + 1099 + ws_conn 1100 + .text( 1101 + serde_json::json!({ 1102 + "error": "2fa_required", 1103 + "flow": flow, 1104 + }).to_string() 1105 + ) 1106 + .await.map_err(|_| AuthenticationError::SocketError)?; 1107 + 1108 + let _ = ws_conn.close(None).await; 1109 + 1110 + return Ok(super::templates::Success { 1111 + icon: user.avatar_url.as_deref().unwrap_or("https://cdn-raw.modrinth.com/placeholder.svg"), 1112 + name: &user.username, 1113 + }.render()); 1114 + } 1115 + } 1116 + 1117 + user_id 1118 + } else { 1119 + oauth_user.create_account(provider, &mut transaction, &client, &file_host, &redis).await? 1120 + }; 1121 + 1122 + let session = issue_session(req, user_id, &mut transaction, &redis).await?; 1123 + transaction.commit().await?; 1124 + 1125 + if let Some(url) = url { 1126 + let redirect_url = format!( 1127 + "{}{}code={}{}", 1128 + url, 1129 + if url.contains('?') { '&' } else { '?' }, 1130 + session.session, 1131 + if user_id_opt.is_none() { 1132 + "&new_account=true" 1133 + } else { 1134 + "" 1135 + } 1136 + ); 1137 + 1138 + Ok(HttpResponse::TemporaryRedirect() 1139 + .append_header(("Location", &*redirect_url)) 1140 + .json(serde_json::json!({ "url": redirect_url }))) 1141 + } else { 1142 + let user = crate::database::models::user_item::User::get_id( 1143 + user_id, 1144 + &**client, 1145 + &redis, 1146 + ) 1147 + .await?.ok_or_else(|| AuthenticationError::InvalidCredentials)?; 1148 + 1149 + let mut ws_conn = { 1150 + let db = sockets.read().await; 1151 + 1152 + let mut x = db 1153 + .auth_sockets 1154 + .get_mut(&state) 1155 + .ok_or_else(|| AuthenticationError::SocketError)?; 1156 + 1157 + x.value_mut().clone() 1158 + }; 1159 + 1160 + ws_conn 1161 + .text( 1162 + serde_json::json!({ 1163 + "code": session.session, 1164 + }).to_string() 1165 + ) 1166 + .await.map_err(|_| AuthenticationError::SocketError)?; 1167 + let _ = ws_conn.close(None).await; 1168 + 1169 + return Ok(super::templates::Success { 1170 + icon: user.avatar_url.as_deref().unwrap_or("https://cdn-raw.modrinth.com/placeholder.svg"), 1171 + name: &user.username, 1172 + }.render()); 1173 + } 1174 + } 1175 + } else { 1176 + Err::<HttpResponse, AuthenticationError>(AuthenticationError::InvalidCredentials) 1177 + } 1178 ~ }.await; |