1use std::collections::HashMap;
2use std::path::Path;
3
4use chrono::{DateTime, Utc};
5use crate_meta::CrateMeta;
6use kellnr_common::account_name::{GroupName, UserName};
7use kellnr_common::canonical_name::CanonicalName;
8use kellnr_common::crate_data::CrateData;
9use kellnr_common::crate_dependents::CrateDependents;
10use kellnr_common::crate_overview::CrateOverview;
11use kellnr_common::cratesio_prefetch_msg::CratesioPrefetchMsg;
12use kellnr_common::index_metadata::IndexMetadata;
13use kellnr_common::original_name::OriginalName;
14use kellnr_common::plain_token::PlainToken;
15use kellnr_common::prefetch::Prefetch;
16use kellnr_common::publish_metadata::PublishMetadata;
17use kellnr_common::version::Version;
18use kellnr_common::webhook::{Webhook, WebhookEvent, WebhookQueue};
19use sea_orm::prelude::async_trait::async_trait;
20use serde::{Deserialize, Serialize};
21
22use crate::error::DbError;
23use crate::{
24 AuthToken, AuthTokenId, CrateId, DocQueueEntry, Group, ToolchainTargetStatus, User, UserFlags,
25 crate_meta,
26};
27
28pub type DbResult<T> = Result<T, DbError>;
29
30#[derive(Debug, PartialEq, Eq)]
31pub enum PrefetchState {
32 UpToDate {
35 etag: String,
36 last_modified: String,
37 },
38 NeedsUpdate(Prefetch),
39 NotFound,
40}
41
42#[derive(Debug, Clone, PartialEq, Eq)]
44pub struct CratesioVersionMeta {
45 pub cksum: String,
46 pub license: Option<String>,
49 pub pubtime: Option<DateTime<Utc>>,
51}
52
53#[derive(Debug, Clone, PartialEq, Eq)]
56pub struct CachedCratesioVersion {
57 pub name: OriginalName,
58 pub version: String,
59}
60
61#[derive(Debug, Clone, PartialEq, Eq)]
63pub enum CrateVisibility {
64 All,
66 User(UserName),
69 Unrestricted,
71}
72
73#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, utoipa::ToSchema)]
75#[serde(rename_all = "lowercase")]
76pub enum CrateSort {
77 #[default]
79 Name,
80 Updated,
82 Downloads,
84}
85
86#[derive(Debug, Clone, Default, PartialEq, Eq)]
90pub struct CrateTagFilter {
91 pub keyword: Option<String>,
92 pub category: Option<String>,
93}
94
95impl CrateTagFilter {
96 pub fn is_empty(&self) -> bool {
97 self.keyword.is_none() && self.category.is_none()
98 }
99}
100
101#[derive(Debug, Clone, PartialEq, Eq)]
103pub struct SessionInfo {
104 pub name: UserName,
105 pub is_admin: bool,
106 pub is_read_only: bool,
107}
108
109#[derive(Debug, Clone, PartialEq, Eq)]
111pub struct OAuth2StateData {
112 pub state: String,
113 pub pkce_verifier: String,
114 pub nonce: String,
115}
116
117#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, utoipa::ToSchema)]
119pub struct ToolchainComponentInfo {
120 pub name: String,
122 pub storage_path: String,
124 pub hash: String,
126 pub size: i64,
128}
129
130impl From<kellnr_entity::toolchain_component::Model> for ToolchainComponentInfo {
131 fn from(c: kellnr_entity::toolchain_component::Model) -> Self {
132 Self {
133 name: c.name,
134 storage_path: c.storage_path,
135 hash: c.hash,
136 size: c.size,
137 }
138 }
139}
140
141#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, utoipa::ToSchema)]
143pub struct ToolchainTargetInfo {
144 pub id: i64,
146 pub target: String,
148 pub storage_path: String,
150 pub hash: String,
152 pub size: i64,
154 pub status: ToolchainTargetStatus,
156 pub components: Vec<ToolchainComponentInfo>,
158}
159
160#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, utoipa::ToSchema)]
162pub struct ToolchainWithTargets {
163 pub id: i64,
165 pub name: String,
167 pub version: String,
169 pub date: String,
171 pub channel: Option<String>,
173 pub created: String,
175 pub targets: Vec<ToolchainTargetInfo>,
177}
178
179#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, utoipa::ToSchema)]
181pub struct ChannelInfo {
182 pub name: String,
184 pub version: String,
186 pub date: String,
188}
189
190#[cfg_attr(feature = "mock", mockall::automock)]
191#[async_trait]
192pub trait DbProvider: Send + Sync {
193 async fn get_last_updated_crate(
194 &self,
195 visibility: &CrateVisibility,
196 ) -> DbResult<Option<(OriginalName, Version)>>;
197 async fn authenticate_user(&self, name: &UserName, pwd: &str) -> DbResult<User>;
198 async fn increase_download_counter(
199 &self,
200 crate_name: &CanonicalName,
201 crate_version: &Version,
202 ) -> DbResult<()>;
203 async fn increase_cached_download_counter(
204 &self,
205 crate_name: &CanonicalName,
206 crate_version: &Version,
207 ) -> DbResult<()>;
208 async fn increase_download_counter_by(
209 &self,
210 crate_name: &CanonicalName,
211 crate_version: &Version,
212 count: u64,
213 ) -> DbResult<()>;
214 async fn increase_cached_download_counter_by(
215 &self,
216 crate_name: &CanonicalName,
217 crate_version: &Version,
218 count: u64,
219 ) -> DbResult<()>;
220 async fn validate_session(&self, session_token: &PlainToken) -> DbResult<SessionInfo>;
221 async fn delete_expired_sessions(&self) -> DbResult<u64>;
224 async fn add_session_token(&self, name: &UserName, session_token: &PlainToken) -> DbResult<()>;
225 async fn delete_user_sessions(&self, user_name: &UserName) -> DbResult<u64>;
227 async fn delete_other_user_sessions(
230 &self,
231 user_name: &UserName,
232 keep_session_token: &PlainToken,
233 ) -> DbResult<u64>;
234 async fn add_crate_user(&self, crate_name: &CanonicalName, user: &UserName) -> DbResult<()>;
235 async fn add_owner(&self, crate_name: &CanonicalName, owner: &UserName) -> DbResult<()>;
238 async fn is_download_restricted(&self, crate_name: &CanonicalName) -> DbResult<bool>;
239 async fn change_download_restricted(
240 &self,
241 crate_name: &CanonicalName,
242 restricted: bool,
243 ) -> DbResult<()>;
244 async fn is_crate_user(&self, crate_name: &CanonicalName, user: &UserName) -> DbResult<bool>;
245 async fn is_owner(&self, crate_name: &CanonicalName, user: &UserName) -> DbResult<bool>;
246 async fn get_crate_id(&self, crate_name: &CanonicalName) -> DbResult<Option<CrateId>>;
247 async fn get_crate_owners(&self, crate_name: &CanonicalName) -> DbResult<Vec<User>>;
248 async fn get_crate_users(&self, crate_name: &CanonicalName) -> DbResult<Vec<User>>;
249 async fn get_crate_versions(&self, crate_name: &CanonicalName) -> DbResult<Vec<Version>>;
250 async fn delete_session_token(&self, session_token: &PlainToken) -> DbResult<()>;
251 async fn delete_user(&self, user_name: &UserName) -> DbResult<()>;
252 async fn change_pwd(&self, user_name: &UserName, new_pwd: &str) -> DbResult<()>;
253 async fn change_read_only_state(&self, user_name: &UserName, state: bool) -> DbResult<()>;
254 async fn change_admin_state(&self, user_name: &UserName, state: bool) -> DbResult<()>;
255 async fn crate_version_exists(&self, crate_id: CrateId, version: &Version) -> DbResult<bool>;
256 async fn get_max_version_from_id(&self, crate_id: CrateId) -> DbResult<Version>;
257 async fn get_max_version_from_name(&self, crate_name: &CanonicalName) -> DbResult<Version>;
258 async fn add_auth_token(&self, name: &str, token: &PlainToken, user: &UserName)
259 -> DbResult<()>;
260 async fn get_user_from_token(&self, token: &PlainToken) -> DbResult<User>;
261 async fn get_auth_token_name(&self, token: &PlainToken) -> DbResult<Option<String>>;
263 async fn get_user(&self, name: &UserName) -> DbResult<User>;
264 async fn get_auth_tokens(&self, user_name: &UserName) -> DbResult<Vec<AuthToken>>;
265 async fn delete_auth_token(&self, user_name: &UserName, id: AuthTokenId) -> DbResult<()>;
268 async fn delete_owners(
273 &self,
274 crate_name: &CanonicalName,
275 owners: &[UserName],
276 allow_ownerless: bool,
277 ) -> DbResult<()>;
278 async fn delete_crate_user(&self, crate_name: &CanonicalName, user: &UserName) -> DbResult<()>;
279 async fn add_user(&self, name: &UserName, pwd: &str, flags: UserFlags) -> DbResult<()>;
280 async fn get_users(&self) -> DbResult<Vec<User>>;
281 async fn add_group(&self, name: &GroupName) -> DbResult<()>;
282 async fn get_groups(&self) -> DbResult<Vec<Group>>;
283 async fn delete_group(&self, name: &GroupName) -> DbResult<()>;
284 async fn add_group_user(&self, group_name: &GroupName, user: &UserName) -> DbResult<()>;
285 async fn delete_group_user(&self, group_name: &GroupName, user: &UserName) -> DbResult<()>;
286 async fn get_group_users(&self, group_name: &GroupName) -> DbResult<Vec<User>>;
287 async fn is_group_user(&self, group_name: &GroupName, user: &UserName) -> DbResult<bool>;
288 async fn add_crate_group(&self, crate_name: &CanonicalName, group: &GroupName) -> DbResult<()>;
289 async fn delete_crate_group(
290 &self,
291 crate_name: &CanonicalName,
292 group: &GroupName,
293 ) -> DbResult<()>;
294 async fn get_crate_groups(&self, crate_name: &CanonicalName) -> DbResult<Vec<Group>>;
295 async fn is_crate_group(&self, crate_name: &CanonicalName, group: &GroupName)
296 -> DbResult<bool>;
297 async fn is_crate_group_user(
298 &self,
299 crate_name: &CanonicalName,
300 user: &UserName,
301 ) -> DbResult<bool>;
302 async fn get_total_unique_crates(&self) -> DbResult<u64>;
303 async fn get_total_crate_versions(&self) -> DbResult<u64>;
304 async fn get_total_downloads(&self) -> DbResult<u64>;
305 async fn get_top_crates_downloads(
306 &self,
307 top: u64,
308 visibility: &CrateVisibility,
309 ) -> DbResult<Vec<(String, u64)>>;
310 async fn get_total_unique_cached_crates(&self) -> DbResult<u64>;
311 async fn get_total_cached_crate_versions(&self) -> DbResult<u64>;
312 async fn get_total_cached_downloads(&self) -> DbResult<u64>;
313 async fn add_doc_queue(
314 &self,
315 krate: &OriginalName,
316 version: &Version,
317 path: &Path,
318 ) -> DbResult<()>;
319 async fn delete_doc_queue(&self, id: i64) -> DbResult<()>;
320 async fn get_doc_queue(&self) -> DbResult<Vec<DocQueueEntry>>;
321 async fn delete_crate(&self, krate: &CanonicalName, version: &Version) -> DbResult<()>;
322 async fn get_crate_meta_list(&self, crate_name: &CanonicalName) -> DbResult<Vec<CrateMeta>>;
323 async fn search_in_crate_name_and_description(
324 &self,
325 contains: &str,
326 limit: u64,
327 offset: u64,
328 cache: bool,
329 visibility: &CrateVisibility,
330 ) -> DbResult<Vec<CrateOverview>>;
331 async fn count_by_crate_name_and_description(
332 &self,
333 contains: &str,
334 cache: bool,
335 visibility: &CrateVisibility,
336 ) -> DbResult<u64>;
337 async fn get_crate_overview_list(
338 &self,
339 limit: u64,
340 offset: u64,
341 cache: bool,
342 visibility: &CrateVisibility,
343 sort: CrateSort,
344 tags: &CrateTagFilter,
345 ) -> DbResult<Vec<CrateOverview>>;
346 async fn count_crate_overview_list(
347 &self,
348 cache: bool,
349 visibility: &CrateVisibility,
350 tags: &CrateTagFilter,
351 ) -> DbResult<u64>;
352 async fn get_crate_data(&self, crate_name: &CanonicalName) -> DbResult<CrateData>;
353 async fn get_crate_dependents(&self, crate_name: &CanonicalName) -> DbResult<CrateDependents>;
357 async fn add_empty_crate(&self, name: &str, created: &DateTime<Utc>) -> DbResult<CrateId>;
358 async fn add_crate(
362 &self,
363 pub_metadata: &PublishMetadata,
364 cksum: &str,
365 size: i64,
366 created: &DateTime<Utc>,
367 owner: &UserName,
368 token_name: Option<String>,
369 ) -> DbResult<CrateId>;
370 async fn update_docs_link(
371 &self,
372 crate_name: &CanonicalName,
373 version: &Version,
374 docs_link: &str,
375 ) -> DbResult<()>;
376 async fn get_prefetch_data(&self, crate_name: &OriginalName) -> DbResult<Prefetch>;
377 async fn is_cratesio_cache_up_to_date(
378 &self,
379 crate_name: &OriginalName,
380 if_none_match: Option<String>,
381 if_modified_since: Option<String>,
382 ) -> DbResult<PrefetchState>;
383 async fn add_cratesio_prefetch_data(
384 &self,
385 crate_name: &OriginalName,
386 etag: &str,
387 last_modified: &str,
388 description: Option<String>,
389 indices: &[IndexMetadata],
390 licenses: &HashMap<String, String>,
391 ) -> DbResult<Prefetch>;
392 async fn remove_deleted_cratesio_versions(
396 &self,
397 crate_name: &OriginalName,
398 upstream_versions: &[String],
399 ) -> DbResult<Vec<CachedCratesioVersion>>;
400 async fn delete_cratesio_crate(
404 &self,
405 crate_name: &OriginalName,
406 ) -> DbResult<Vec<CachedCratesioVersion>>;
407 async fn get_cratesio_index_update_list(&self) -> DbResult<Vec<CratesioPrefetchMsg>>;
408 async fn get_cratesio_version_meta(
411 &self,
412 crate_name: &CanonicalName,
413 version: &Version,
414 ) -> DbResult<Option<CratesioVersionMeta>>;
415 async fn get_crate_license(
418 &self,
419 crate_name: &CanonicalName,
420 version: &Version,
421 ) -> DbResult<Option<String>>;
422 async fn unyank_crate(&self, crate_name: &CanonicalName, version: &Version) -> DbResult<()>;
423 async fn yank_crate(&self, crate_name: &CanonicalName, version: &Version) -> DbResult<()>;
424 async fn register_webhook(&self, webhook: Webhook) -> DbResult<String>;
425 async fn delete_webhook(&self, id: &str) -> DbResult<()>;
426 async fn get_webhook(&self, id: &str) -> DbResult<Webhook>;
427 async fn get_all_webhooks(&self) -> DbResult<Vec<Webhook>>;
428 async fn add_webhook_queue(
432 &self,
433 event: WebhookEvent,
434 payload: serde_json::Value,
435 ) -> DbResult<()>;
436 async fn get_pending_webhook_queue_entries(
438 &self,
439 timestamp: DateTime<Utc>,
440 ) -> DbResult<Vec<WebhookQueue>>;
441 async fn update_webhook_queue(
442 &self,
443 id: &str,
444 last_attempt: DateTime<Utc>,
445 next_attempt: DateTime<Utc>,
446 ) -> DbResult<()>;
447 async fn delete_webhook_queue(&self, id: &str) -> DbResult<()>;
448
449 async fn get_user_by_oauth2_identity(
452 &self,
453 issuer: &str,
454 subject: &str,
455 ) -> DbResult<Option<User>>;
456
457 async fn has_oauth2_admin(&self) -> DbResult<bool>;
463
464 async fn create_oauth2_user(
466 &self,
467 username: &UserName,
468 issuer: &str,
469 subject: &str,
470 email: Option<String>,
471 flags: UserFlags,
472 ) -> DbResult<User>;
473
474 async fn store_oauth2_state(
477 &self,
478 state: &str,
479 pkce_verifier: &str,
480 nonce: &str,
481 ) -> DbResult<()>;
482
483 async fn get_and_delete_oauth2_state(&self, state: &str) -> DbResult<Option<OAuth2StateData>>;
485
486 async fn cleanup_expired_oauth2_states(&self) -> DbResult<u64>;
488
489 async fn is_username_available(&self, username: &UserName) -> DbResult<bool>;
491
492 async fn add_toolchain(
495 &self,
496 name: &str,
497 version: &str,
498 date: &str,
499 channel: Option<String>,
500 ) -> DbResult<i64>;
501
502 async fn add_toolchain_target(
504 &self,
505 toolchain_id: i64,
506 target: &str,
507 storage_path: &str,
508 hash: &str,
509 size: i64,
510 ) -> DbResult<i64>;
511
512 async fn add_toolchain_component(
514 &self,
515 target_id: i64,
516 name: &str,
517 storage_path: &str,
518 hash: &str,
519 size: i64,
520 ) -> DbResult<()>;
521
522 async fn is_toolchain_component_stored_at(&self, storage_path: &str) -> DbResult<bool>;
524
525 async fn set_target_status(
527 &self,
528 target_id: i64,
529 status: ToolchainTargetStatus,
530 ) -> DbResult<()>;
531
532 async fn fail_processing_toolchain_targets(&self) -> DbResult<u64>;
535
536 async fn get_toolchain_by_channel(
538 &self,
539 channel: &str,
540 ) -> DbResult<Option<ToolchainWithTargets>>;
541
542 async fn get_toolchain_by_version(
544 &self,
545 name: &str,
546 version: &str,
547 ) -> DbResult<Option<ToolchainWithTargets>>;
548
549 async fn list_toolchains(&self) -> DbResult<Vec<ToolchainWithTargets>>;
551
552 async fn delete_toolchain(&self, name: &str, version: &str) -> DbResult<()>;
554
555 async fn delete_toolchain_target(
557 &self,
558 name: &str,
559 version: &str,
560 target: &str,
561 ) -> DbResult<()>;
562
563 async fn set_channel(&self, channel: &str, name: &str, version: &str) -> DbResult<()>;
565
566 async fn get_channels(&self) -> DbResult<Vec<ChannelInfo>>;
568
569 async fn get_crate_original_name(
572 &self,
573 crate_name: &CanonicalName,
574 ) -> DbResult<Option<OriginalName>>;
575
576 async fn get_original_name(
578 &self,
579 crate_name: &CanonicalName,
580 version: &Version,
581 ) -> DbResult<Option<OriginalName>>;
582}
583
584#[cfg(feature = "mock")]
585pub mod mock {
586 pub use super::MockDbProvider as MockDb;
587}