You've already forked AstralRinth
forked from didirus/AstralRinth
Tests (#719)
* computer switch * some fixes; github action * added pr to master * sqlx database setup * switched intial GHA test db * removed sqlx database setup * unfinished patch route * bug fixes + tests * more tests, more fixes, cargo fmt * merge fixes * more tests, full reorganization * fmt, clippy * sqlx-data * revs * removed comments * delete revs
This commit is contained in:
@@ -3,16 +3,17 @@ use crate::auth::session::issue_session;
|
||||
use crate::auth::validate::get_user_record_from_bearer_token;
|
||||
use crate::auth::{get_user_from_headers, AuthenticationError};
|
||||
use crate::database::models::flow_item::Flow;
|
||||
use crate::database::redis::RedisPool;
|
||||
use crate::file_hosting::FileHost;
|
||||
use crate::models::ids::base62_impl::{parse_base62, to_base62};
|
||||
use crate::models::ids::random_base62_rng;
|
||||
use crate::models::pats::Scopes;
|
||||
use crate::models::users::{Badges, Role};
|
||||
use crate::parse_strings_from_var;
|
||||
use crate::queue::session::AuthQueue;
|
||||
use crate::queue::socket::ActiveSockets;
|
||||
use crate::routes::ApiError;
|
||||
use crate::util::captcha::check_turnstile_captcha;
|
||||
use crate::util::env::parse_strings_from_var;
|
||||
use crate::util::ext::{get_image_content_type, get_image_ext};
|
||||
use crate::util::validate::{validation_errors_to_string, RE_URL_SAFE};
|
||||
use actix_web::web::{scope, Data, Payload, Query, ServiceConfig};
|
||||
@@ -54,7 +55,7 @@ pub fn config(cfg: &mut ServiceConfig) {
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Eq, PartialEq, Clone, Copy)]
|
||||
#[derive(Serialize, Deserialize, Default, Eq, PartialEq, Clone, Copy, Debug)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum AuthProvider {
|
||||
#[default]
|
||||
@@ -84,7 +85,7 @@ impl TempUser {
|
||||
transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
client: &PgPool,
|
||||
file_host: &Arc<dyn FileHost + Send + Sync>,
|
||||
redis: &deadpool_redis::Pool,
|
||||
redis: &RedisPool,
|
||||
) -> Result<crate::database::models::UserId, AuthenticationError> {
|
||||
if let Some(email) = &self.email {
|
||||
if crate::database::models::User::get_email(email, client)
|
||||
@@ -907,7 +908,7 @@ pub async fn init(
|
||||
req: HttpRequest,
|
||||
Query(info): Query<AuthorizationInit>, // callback url
|
||||
client: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, AuthenticationError> {
|
||||
let url = url::Url::parse(&info.url).map_err(|_| AuthenticationError::Url)?;
|
||||
@@ -959,7 +960,7 @@ pub async fn ws_init(
|
||||
Query(info): Query<WsInit>,
|
||||
body: Payload,
|
||||
db: Data<RwLock<ActiveSockets>>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
let (res, session, _msg_stream) = actix_ws::handle(&req, body)?;
|
||||
|
||||
@@ -967,7 +968,7 @@ pub async fn ws_init(
|
||||
mut ws_stream: actix_ws::Session,
|
||||
info: WsInit,
|
||||
db: Data<RwLock<ActiveSockets>>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
) -> Result<(), Closed> {
|
||||
let flow = Flow::OAuth {
|
||||
user_id: None,
|
||||
@@ -1003,7 +1004,7 @@ pub async fn auth_callback(
|
||||
active_sockets: Data<RwLock<ActiveSockets>>,
|
||||
client: Data<PgPool>,
|
||||
file_host: Data<Arc<dyn FileHost + Send + Sync>>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
) -> Result<HttpResponse, super::templates::ErrorPage> {
|
||||
let state_string = query
|
||||
.get("state")
|
||||
@@ -1210,7 +1211,7 @@ pub struct DeleteAuthProvider {
|
||||
pub async fn delete_auth_provider(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
delete_provider: web::Json<DeleteAuthProvider>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
@@ -1297,7 +1298,7 @@ pub struct NewAccount {
|
||||
pub async fn create_account_with_password(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
new_account: web::Json<NewAccount>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
new_account
|
||||
@@ -1414,7 +1415,7 @@ pub struct Login {
|
||||
pub async fn login_password(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
login: web::Json<Login>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
if !check_turnstile_captcha(&req, &login.challenge).await? {
|
||||
@@ -1478,7 +1479,7 @@ async fn validate_2fa_code(
|
||||
secret: String,
|
||||
allow_backup: bool,
|
||||
user_id: crate::database::models::UserId,
|
||||
redis: &deadpool_redis::Pool,
|
||||
redis: &RedisPool,
|
||||
pool: &PgPool,
|
||||
transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
) -> Result<bool, AuthenticationError> {
|
||||
@@ -1530,7 +1531,7 @@ async fn validate_2fa_code(
|
||||
pub async fn login_2fa(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
login: web::Json<Login2FA>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let flow = Flow::get(&login.flow, &redis)
|
||||
@@ -1577,7 +1578,7 @@ pub async fn login_2fa(
|
||||
pub async fn begin_2fa_flow(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let user = get_user_from_headers(
|
||||
@@ -1616,7 +1617,7 @@ pub async fn begin_2fa_flow(
|
||||
pub async fn finish_2fa_flow(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
login: web::Json<Login2FA>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
@@ -1739,7 +1740,7 @@ pub struct Remove2FA {
|
||||
pub async fn remove_2fa(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
login: web::Json<Remove2FA>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
@@ -1821,7 +1822,7 @@ pub struct ResetPassword {
|
||||
pub async fn reset_password_begin(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
reset_password: web::Json<ResetPassword>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
if !check_turnstile_captcha(&req, &reset_password.challenge).await? {
|
||||
@@ -1866,7 +1867,7 @@ pub struct ChangePassword {
|
||||
pub async fn change_password(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
change_password: web::Json<ChangePassword>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
@@ -2007,7 +2008,7 @@ pub struct SetEmail {
|
||||
pub async fn set_email(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
email: web::Json<SetEmail>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
@@ -2073,7 +2074,7 @@ pub async fn set_email(
|
||||
pub async fn resend_verify_email(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let user = get_user_from_headers(
|
||||
@@ -2118,7 +2119,7 @@ pub struct VerifyEmail {
|
||||
#[post("email/verify")]
|
||||
pub async fn verify_email(
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
email: web::Json<VerifyEmail>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let flow = Flow::get(&email.flow, &redis).await?;
|
||||
@@ -2168,7 +2169,7 @@ pub async fn verify_email(
|
||||
pub async fn subscribe_newsletter(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let user = get_user_from_headers(
|
||||
|
||||
@@ -4,6 +4,7 @@ use crate::database::models::generate_pat_id;
|
||||
use crate::auth::get_user_from_headers;
|
||||
use crate::routes::ApiError;
|
||||
|
||||
use crate::database::redis::RedisPool;
|
||||
use actix_web::web::{self, Data};
|
||||
use actix_web::{delete, get, patch, post, HttpRequest, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
@@ -30,7 +31,7 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
||||
pub async fn get_pats(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let user = get_user_from_headers(
|
||||
@@ -73,14 +74,14 @@ pub async fn create_pat(
|
||||
req: HttpRequest,
|
||||
info: web::Json<NewPersonalAccessToken>,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
info.0
|
||||
.validate()
|
||||
.map_err(|err| ApiError::InvalidInput(validation_errors_to_string(err, None)))?;
|
||||
|
||||
if info.scopes.restricted() {
|
||||
if info.scopes.is_restricted() {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"Invalid scopes requested!".to_string(),
|
||||
));
|
||||
@@ -159,7 +160,7 @@ pub async fn edit_pat(
|
||||
id: web::Path<(String,)>,
|
||||
info: web::Json<ModifyPersonalAccessToken>,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let user = get_user_from_headers(
|
||||
@@ -180,7 +181,7 @@ pub async fn edit_pat(
|
||||
let mut transaction = pool.begin().await?;
|
||||
|
||||
if let Some(scopes) = &info.scopes {
|
||||
if scopes.restricted() {
|
||||
if scopes.is_restricted() {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"Invalid scopes requested!".to_string(),
|
||||
));
|
||||
@@ -248,7 +249,7 @@ pub async fn delete_pat(
|
||||
req: HttpRequest,
|
||||
id: web::Path<(String,)>,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let user = get_user_from_headers(
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::auth::{get_user_from_headers, AuthenticationError};
|
||||
use crate::database::models::session_item::Session as DBSession;
|
||||
use crate::database::models::session_item::SessionBuilder;
|
||||
use crate::database::models::UserId;
|
||||
use crate::database::redis::RedisPool;
|
||||
use crate::models::pats::Scopes;
|
||||
use crate::models::sessions::Session;
|
||||
use crate::queue::session::AuthQueue;
|
||||
@@ -86,7 +87,7 @@ pub async fn issue_session(
|
||||
req: HttpRequest,
|
||||
user_id: UserId,
|
||||
transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
redis: &deadpool_redis::Pool,
|
||||
redis: &RedisPool,
|
||||
) -> Result<DBSession, AuthenticationError> {
|
||||
let metadata = get_session_metadata(&req).await?;
|
||||
|
||||
@@ -132,7 +133,7 @@ pub async fn issue_session(
|
||||
pub async fn list(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let current_user = get_user_from_headers(
|
||||
@@ -167,7 +168,7 @@ pub async fn delete(
|
||||
info: web::Path<(String,)>,
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let current_user = get_user_from_headers(
|
||||
@@ -206,7 +207,7 @@ pub async fn delete(
|
||||
pub async fn refresh(
|
||||
req: HttpRequest,
|
||||
pool: Data<PgPool>,
|
||||
redis: Data<deadpool_redis::Pool>,
|
||||
redis: Data<RedisPool>,
|
||||
session_queue: Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let current_user = get_user_from_headers(&req, &**pool, &redis, &session_queue, None)
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::auth::flows::AuthProvider;
|
||||
use crate::auth::session::get_session_metadata;
|
||||
use crate::auth::AuthenticationError;
|
||||
use crate::database::models::user_item;
|
||||
use crate::database::redis::RedisPool;
|
||||
use crate::models::pats::Scopes;
|
||||
use crate::models::users::{Role, User, UserId, UserPayoutData};
|
||||
use crate::queue::session::AuthQueue;
|
||||
@@ -12,7 +13,7 @@ use reqwest::header::{HeaderValue, AUTHORIZATION};
|
||||
pub async fn get_user_from_headers<'a, E>(
|
||||
req: &HttpRequest,
|
||||
executor: E,
|
||||
redis: &deadpool_redis::Pool,
|
||||
redis: &RedisPool,
|
||||
session_queue: &AuthQueue,
|
||||
required_scopes: Option<&[Scopes]>,
|
||||
) -> Result<(Scopes, User), AuthenticationError>
|
||||
@@ -82,7 +83,7 @@ pub async fn get_user_record_from_bearer_token<'a, 'b, E>(
|
||||
req: &HttpRequest,
|
||||
token: Option<&str>,
|
||||
executor: E,
|
||||
redis: &deadpool_redis::Pool,
|
||||
redis: &RedisPool,
|
||||
session_queue: &AuthQueue,
|
||||
) -> Result<Option<(Scopes, user_item::User)>, AuthenticationError>
|
||||
where
|
||||
@@ -140,7 +141,7 @@ where
|
||||
session_queue.add_session(session.id, metadata).await;
|
||||
}
|
||||
|
||||
user.map(|x| (Scopes::ALL, x))
|
||||
user.map(|x| (Scopes::all(), x))
|
||||
}
|
||||
Some(("github", _)) | Some(("gho", _)) | Some(("ghp", _)) => {
|
||||
let user = AuthProvider::GitHub.get_user(token).await?;
|
||||
@@ -153,7 +154,7 @@ where
|
||||
)
|
||||
.await?;
|
||||
|
||||
user.map(|x| (Scopes::NOT_RESTRICTED, x))
|
||||
user.map(|x| ((Scopes::all() ^ Scopes::restricted()), x))
|
||||
}
|
||||
_ => return Err(AuthenticationError::InvalidAuthMethod),
|
||||
};
|
||||
@@ -163,13 +164,14 @@ where
|
||||
pub async fn check_is_moderator_from_headers<'a, 'b, E>(
|
||||
req: &HttpRequest,
|
||||
executor: E,
|
||||
redis: &deadpool_redis::Pool,
|
||||
redis: &RedisPool,
|
||||
session_queue: &AuthQueue,
|
||||
required_scopes: Option<&[Scopes]>,
|
||||
) -> Result<User, AuthenticationError>
|
||||
where
|
||||
E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy,
|
||||
{
|
||||
let user = get_user_from_headers(req, executor, redis, session_queue, None)
|
||||
let user = get_user_from_headers(req, executor, redis, session_queue, required_scopes)
|
||||
.await?
|
||||
.1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user