Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,22 @@

-- Inserts 5 dummy users for testing, with slight differences
-- 'Friend' and 'enemy' function like 'user', but we can use them to simulate 'other' users that may or may not be able to access certain things
-- IDs 1-5, 1-5
INSERT INTO users (id, username, email, role) VALUES (1, 'Admin', 'admin@modrinth.com', 'admin');
INSERT INTO users (id, username, email, role)
VALUES (2, 'Moderator', 'moderator@modrinth.com', 'moderator');
INSERT INTO users (id, username, email, role) VALUES (3, 'User', 'user@modrinth.com', 'developer');
INSERT INTO users (id, username, email, role)
VALUES (4, 'Friend', 'friend@modrinth.com', 'developer');
INSERT INTO users (id, username, email, role)
VALUES (5, 'Enemy', 'enemy@modrinth.com', 'developer');
VALUES ({{user_id::ADMIN}}, 'Admin', 'admin@modrinth.com', 'admin'),
({{user_id::MODERATOR}}, 'Moderator', 'moderator@modrinth.com', 'moderator'),
({{user_id::USER}}, 'User', 'user@modrinth.com', 'developer'),
({{user_id::FRIEND}}, 'Friend', 'friend@modrinth.com', 'developer'),
({{user_id::ENEMY}}, 'Enemy', 'enemy@modrinth.com', 'developer');

-- Full PATs for each user, with different scopes
-- These are not legal PATs, as they contain all scopes- they mimic permissions of a logged in user
-- IDs: 50-54, o p q r s
INSERT INTO pats (id, user_id, name, access_token, scopes, expires) VALUES (50, 1, 'admin-pat', 'mrp_patadmin', $1, '2030-08-18 15:48:58.435729+00');
INSERT INTO pats (id, user_id, name, access_token, scopes, expires) VALUES (51, 2, 'moderator-pat', 'mrp_patmoderator', $1, '2030-08-18 15:48:58.435729+00');
INSERT INTO pats (id, user_id, name, access_token, scopes, expires) VALUES (52, 3, 'user-pat', 'mrp_patuser', $1, '2030-08-18 15:48:58.435729+00');
INSERT INTO pats (id, user_id, name, access_token, scopes, expires) VALUES (53, 4, 'friend-pat', 'mrp_patfriend', $1, '2030-08-18 15:48:58.435729+00');
INSERT INTO pats (id, user_id, name, access_token, scopes, expires) VALUES (54, 5, 'enemy-pat', 'mrp_patenemy', $1, '2030-08-18 15:48:58.435729+00');
INSERT INTO pats (id, user_id, name, access_token, scopes, expires)
VALUES (50, {{user_id::ADMIN}}, 'admin-pat', '{{pat::ADMIN}}', {{all_scopes}}, '2030-08-18 15:48:58.435729+00'),
(51, {{user_id::MODERATOR}}, 'moderator-pat', '{{pat::MODERATOR}}', {{all_scopes}}, '2030-08-18 15:48:58.435729+00'),
(52, {{user_id::USER}}, 'user-pat', '{{pat::USER}}', {{all_scopes}}, '2030-08-18 15:48:58.435729+00'),
(53, {{user_id::FRIEND}}, 'friend-pat', '{{pat::FRIEND}}', {{all_scopes}}, '2030-08-18 15:48:58.435729+00'),
(54, {{user_id::ENEMY}}, 'enemy-pat', '{{pat::ENEMY}}', {{all_scopes}}, '2030-08-18 15:48:58.435729+00');

INSERT INTO loaders (id, loader) VALUES (5, 'fabric');
INSERT INTO loaders_project_types (joining_loader_id, joining_project_type_id) VALUES (5, 1);
Expand Down Expand Up @@ -119,7 +117,7 @@ VALUES (
1,
'oauth_client_alpha',
NULL,
$1,
{{all_scopes}},
'4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1',
3
);
Expand Down
3 changes: 2 additions & 1 deletion apps/labrinth/src/database/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ pub use models::DBImage;
pub use models::DBProject;
pub use models::DBVersion;
pub use postgres_database::{
ReadOnlyPgPool, check_for_migrations, connect_all, register_and_set_metrics,
MIGRATOR, ReadOnlyPgPool, check_for_migrations, connect_all,
register_and_set_metrics,
};
28 changes: 20 additions & 8 deletions apps/labrinth/src/database/postgres_database.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use eyre::Context;
use prometheus::{IntGauge, Registry};
use sqlx::migrate::MigrateDatabase;
use sqlx::migrate::{MigrateDatabase, Migrator};
use sqlx::postgres::{PgPool, PgPoolOptions};
use sqlx::{Connection, PgConnection, Postgres};
use std::ops::{Deref, DerefMut};
Expand Down Expand Up @@ -75,25 +76,36 @@ pub async fn connect_all() -> Result<(PgPool, ReadOnlyPgPool), sqlx::Error> {
Ok((pool, ro))
}
}
pub async fn check_for_migrations() -> Result<(), sqlx::Error> {
let uri = dotenvy::var("DATABASE_URL").expect("`DATABASE_URL` not in .env");

pub async fn check_for_migrations() -> eyre::Result<()> {
let uri =
dotenvy::var("DATABASE_URL").wrap_err("`DATABASE_URL` not in .env")?;
let uri = uri.as_str();
if !Postgres::database_exists(uri).await? {
if !Postgres::database_exists(uri)
.await
.wrap_err("failed to check if database exists")?
{
info!("Creating database...");
Postgres::create_database(uri).await?;
Postgres::create_database(uri)
.await
.wrap_err("failed to create database")?;
}

info!("Applying migrations...");

let mut conn: PgConnection = PgConnection::connect(uri).await?;
sqlx::migrate!()
let mut conn: PgConnection = PgConnection::connect(uri)
.await
.wrap_err("failed to connect to database")?;
MIGRATOR
.run(&mut conn)
.await
.expect("Error while running database migrations!");
.wrap_err("failed to run database migrations")?;

Ok(())
}

pub static MIGRATOR: Migrator = sqlx::migrate!();

pub async fn register_and_set_metrics(
pool: &PgPool,
registry: &Registry,
Expand Down
1 change: 1 addition & 0 deletions apps/labrinth/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub mod routes;
pub mod scheduler;
pub mod search;
pub mod sync;
pub mod test;
pub mod util;
pub mod validate;

Expand Down
81 changes: 81 additions & 0 deletions apps/labrinth/src/test/db.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use eyre::{Context, Result};
use sqlx::{Executor, PgPool};

/// Static personal access token for use in [`AppendPat`].
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Pat(pub &'static str);

/// Dummy [`Pat`]s.
#[allow(missing_docs, reason = "self-explanatory")]
pub mod pat {
use super::Pat;

pub const ADMIN: Pat = Pat("mrp_patadmin");
pub const MODERATOR: Pat = Pat("mrp_patmoderator");
pub const USER: Pat = Pat("mrp_patuser");
pub const FRIEND: Pat = Pat("mrp_patfriend");
pub const ENEMY: Pat = Pat("mrp_patenemy");
}

/// See [`AppendPat::append_pat`].
pub trait AppendPat {
/// Appends a [`Pat`] authorization token to an
/// [`actix_web::test::TestRequest`].
#[must_use]
fn append_pat(self, pat: Pat) -> Self;
}

impl AppendPat for actix_web::test::TestRequest {
fn append_pat(self, pat: Pat) -> Self {
self.append_header(("Authorization", pat.0))
}
}

/// Dummy [`DBUserId`]s.
///
/// [`DBUserId`]: crate::database::models::DBUserId
pub mod user_id {
use crate::database::models::DBUserId;

pub const ADMIN: DBUserId = DBUserId(1);
pub const MODERATOR: DBUserId = DBUserId(2);
pub const USER: DBUserId = DBUserId(3);
pub const FRIEND: DBUserId = DBUserId(4);
pub const ENEMY: DBUserId = DBUserId(5);
}

/// Initialize a database with dummy fixture data.
///
/// # Errors
///
/// Errors if the fixture could not be applied.
pub async fn add_dummy_data(db: &PgPool) -> Result<()> {
db.execute(
include_str!("../../fixtures/dummy_data.sql")
//
.replace("{{user_id::ADMIN}}", &user_id::ADMIN.0.to_string())
.replace(
"{{user_id::MODERATOR}}",
&user_id::MODERATOR.0.to_string(),
)
.replace("{{user_id::USER}}", &user_id::USER.0.to_string())
.replace("{{user_id::FRIEND}}", &user_id::FRIEND.0.to_string())
.replace("{{user_id::ENEMY}}", &user_id::ENEMY.0.to_string())
//
.replace("{{pat::ADMIN}}", pat::ADMIN.0)
.replace("{{pat::MODERATOR}}", pat::MODERATOR.0)
.replace("{{pat::USER}}", pat::USER.0)
.replace("{{pat::FRIEND}}", pat::FRIEND.0)
.replace("{{pat::ENEMY}}", pat::ENEMY.0)
//
.replace(
"{{all_scopes}}",
&crate::models::pats::Scopes::all().bits().to_string(),
)
.as_str(),
)
.await
.wrap_err("failed to add dummy data")?;

Ok(())
}
1 change: 1 addition & 0 deletions apps/labrinth/src/test/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod db;
10 changes: 1 addition & 9 deletions apps/labrinth/tests/common/dummy_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@ use labrinth::models::ids::ProjectId;
use labrinth::models::{
oauth_clients::OAuthClient,
organizations::Organization,
pats::Scopes,
projects::{Project, Version},
};
use serde_json::json;
use sqlx::Executor;
use zip::{CompressionMethod, ZipWriter, write::FileOptions};

use super::{
Expand Down Expand Up @@ -291,13 +289,7 @@ pub async fn add_dummy_data(api: &ApiV3, db: TemporaryDatabase) -> DummyData {
// Adds basic dummy data to the database directly with sql (user, pats)
let pool = &db.pool.clone();

pool.execute(
include_str!("../fixtures/dummy_data.sql")
.replace("$1", &Scopes::all().bits().to_string())
.as_str(),
)
.await
.unwrap();
labrinth::test::db::add_dummy_data(pool).await.unwrap();

let (alpha_project, alpha_version) = add_project_alpha(api).await;
let (beta_project, beta_version) = add_project_beta(api).await;
Expand Down