Skip to content

Commit

Permalink
drop the old DbPool from AppState (#603)
Browse files Browse the repository at this point in the history
* 1. round of cleanup

* clippy is mostly happy again

* `DbPool` removed from `AppState` and all errors fixed

* updated internal notes + fully removed `db_backup()` since hiqlite has it built-in

* all tests are green again
  • Loading branch information
sebadob authored Nov 8, 2024
1 parent dac3892 commit 0578be3
Show file tree
Hide file tree
Showing 73 changed files with 826 additions and 1,379 deletions.
31 changes: 5 additions & 26 deletions dev_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,21 @@

## CURRENT WORK

- [x] migrate `api`
- [x] migrate `api_types`
- [x] migrate `bin`
- [x] migrate `common`
- [x] migrate `error`
- [x] migrate `middlewares`
- [ ] migrate `models` (below-mentioned migration/* and app_state missing)
- [x] migrate `notify`
- [x] migrate `schedulers`
- [x] migrate `service`

- migrate each model step by step
- create proper direct query for users in `src/schedulers/src/passwords.rs`
- `MIGRATE_DB_FROM` for Hiqlite -> implement backup restore from local fs in Hiqlite
- modules left for the end, after main tasks are finished:
- `src/models/src/migration/mod.rs`
- `src/models/src/migration/db_migrate.rs`
- `src/models/src/app_state.rs`

### After finished Hiqlite migration

- check changed session invalidation functions
- fix `DbType::from_str`
- cleanup `DbPool` creation in `AppState`
- remove the `sqlite` feature from `sqlx` to really make sure nothing has been forgotten
- add an index (signature, created_at) to `jwks`

#### Update for the Changelog

- POST /clients does not return the created client anymore

## Documentation TODO

- breaking: only a single container from now on
- `HealthResponse` response has been changed with Hiqlite -> breaking change
- database backup config has been changed slightly
- restore from backup has changed slightly
- write a small guide on how to migrate from existing sqlite to hiqlite

## Stage 1 - essentials

Expand All @@ -59,6 +40,4 @@
## Stage 3 - Possible nice to haves

- impl experimental `dilithium` alg for token signing to become quantum safe
- 'rauthy-migrate' project to help migrating to rauthy? probably when doing benchmarks anyway and use it
for dummy data?
- custom event listener template to build own implementation? -> only if NATS will be implemented maybe?
- custom event listener template to build own implementation?
2 changes: 2 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ test-postgres test="": test-backend-stop postgres-stop postgres-start
./target/debug/rauthy test &
echo $! > {{ file_test_pid }}

sleep 1

if cargo test {{ test }}; then
echo "All SQLite tests successful"
just test-backend-stop
Expand Down
2 changes: 2 additions & 0 deletions rauthy.test.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
# !!! DO NOT USE IN PRODUCTION !!!
DEV_MODE=true

DATABASE_URL=postgresql://rauthy:123SuperSafe@localhost:5432/rauthy

AUTH_HEADERS_ENABLE=true

PASSWORD_RESET_COOKIE_BINDING=true
Expand Down
17 changes: 5 additions & 12 deletions src/api/src/api_keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use actix_web_validator::Json;
use mime_guess::mime::TEXT_PLAIN_UTF_8;
use rauthy_api_types::api_keys::{ApiKeyRequest, ApiKeyResponse, ApiKeysResponse};
use rauthy_error::{ErrorResponse, ErrorResponseType};
use rauthy_models::app_state::AppState;
use rauthy_models::entity::api_keys::ApiKeyEntity;

/// Returns all API Keys
Expand All @@ -22,13 +21,10 @@ use rauthy_models::entity::api_keys::ApiKeyEntity;
),
)]
#[get("/api_keys")]
pub async fn get_api_keys(
data: web::Data<AppState>,
principal: ReqPrincipal,
) -> Result<HttpResponse, ErrorResponse> {
pub async fn get_api_keys(principal: ReqPrincipal) -> Result<HttpResponse, ErrorResponse> {
principal.validate_admin_session()?;

let entities = ApiKeyEntity::find_all(&data).await?;
let entities = ApiKeyEntity::find_all().await?;
let mut keys = Vec::with_capacity(entities.len());
for entity in entities {
let key = entity.into_api_key()?;
Expand Down Expand Up @@ -86,7 +82,6 @@ pub async fn post_api_key(
)]
#[put("/api_keys/{name}")]
pub async fn put_api_key(
data: web::Data<AppState>,
principal: ReqPrincipal,
name: web::Path<String>,
payload: Json<ApiKeyRequest>,
Expand All @@ -103,7 +98,7 @@ pub async fn put_api_key(
}

let access = req.access.into_iter().map(|a| a.into()).collect();
ApiKeyEntity::update(&data, &name, req.exp, access).await?;
ApiKeyEntity::update(&name, req.exp, access).await?;

Ok(HttpResponse::Ok().finish())
}
Expand All @@ -124,14 +119,13 @@ pub async fn put_api_key(
)]
#[delete("/api_keys/{name}")]
pub async fn delete_api_key(
data: web::Data<AppState>,
principal: ReqPrincipal,
name: web::Path<String>,
) -> Result<HttpResponse, ErrorResponse> {
principal.validate_admin_session()?;

let name = name.into_inner();
ApiKeyEntity::delete(&data, &name).await?;
ApiKeyEntity::delete(&name).await?;

Ok(HttpResponse::Ok().finish())
}
Expand Down Expand Up @@ -190,14 +184,13 @@ pub async fn get_api_key_test(
)]
#[put("/api_keys/{name}/secret")]
pub async fn put_api_key_secret(
data: web::Data<AppState>,
principal: ReqPrincipal,
name: web::Path<String>,
) -> Result<HttpResponse, ErrorResponse> {
principal.validate_admin_session()?;

let name = name.into_inner();
let secret = ApiKeyEntity::generate_secret(&data, &name).await?;
let secret = ApiKeyEntity::generate_secret(&name).await?;

Ok(HttpResponse::Ok()
.content_type(TEXT_PLAIN_UTF_8)
Expand Down
56 changes: 17 additions & 39 deletions src/api/src/auth_providers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,10 @@ use tracing::debug;
),
)]
#[post("/providers")]
pub async fn post_providers(
data: web::Data<AppState>,
principal: ReqPrincipal,
) -> Result<HttpResponse, ErrorResponse> {
pub async fn post_providers(principal: ReqPrincipal) -> Result<HttpResponse, ErrorResponse> {
principal.validate_admin_session()?;

let providers = AuthProvider::find_all(&data).await?;
let providers = AuthProvider::find_all().await?;
let mut resp = Vec::with_capacity(providers.len());
for provider in providers {
resp.push(ProviderResponse::try_from(provider)?);
Expand All @@ -66,7 +63,6 @@ pub async fn post_providers(
)]
#[post("/providers/create")]
pub async fn post_provider(
data: web::Data<AppState>,
payload: Json<ProviderRequest>,
principal: ReqPrincipal,
) -> Result<HttpResponse, ErrorResponse> {
Expand All @@ -79,7 +75,7 @@ pub async fn post_provider(
));
}

let provider = AuthProvider::create(&data, payload.into_inner()).await?;
let provider = AuthProvider::create(payload.into_inner()).await?;
Ok(HttpResponse::Ok().json(ProviderResponse::try_from(provider)?))
}

Expand Down Expand Up @@ -133,14 +129,13 @@ pub async fn post_provider_lookup(
)]
#[post("/providers/login")]
pub async fn post_provider_login(
data: web::Data<AppState>,
payload: Json<ProviderLoginRequest>,
principal: ReqPrincipal,
) -> Result<HttpResponse, ErrorResponse> {
principal.validate_session_auth_or_init()?;

let payload = payload.into_inner();
let (cookie, xsrf_token, location) = AuthProviderCallback::login_start(&data, payload).await?;
let (cookie, xsrf_token, location) = AuthProviderCallback::login_start(payload).await?;

Ok(HttpResponse::Accepted()
.insert_header((LOCATION, location))
Expand All @@ -149,11 +144,8 @@ pub async fn post_provider_login(
}

#[get("/providers/callback")]
pub async fn get_provider_callback_html(
data: web::Data<AppState>,
req: HttpRequest,
) -> Result<HttpResponse, ErrorResponse> {
let colors = ColorEntity::find_rauthy(&data).await?;
pub async fn get_provider_callback_html(req: HttpRequest) -> Result<HttpResponse, ErrorResponse> {
let colors = ColorEntity::find_rauthy().await?;
let lang = Language::try_from(&req).unwrap_or_default();
let body = ProviderCallbackHtml::build(&colors, &lang);

Expand Down Expand Up @@ -218,14 +210,11 @@ pub async fn post_provider_callback(
),
)]
#[delete("/providers/link")]
pub async fn delete_provider_link(
data: web::Data<AppState>,
principal: ReqPrincipal,
) -> Result<HttpResponse, ErrorResponse> {
pub async fn delete_provider_link(principal: ReqPrincipal) -> Result<HttpResponse, ErrorResponse> {
principal.validate_session_auth()?;

let user_id = principal.user_id()?.to_string();
let user = User::provider_unlink(&data, user_id).await?;
let user = User::provider_unlink(user_id).await?;
Ok(HttpResponse::Ok().json(user))
}

Expand All @@ -242,12 +231,10 @@ pub async fn delete_provider_link(
),
)]
#[get("/providers/minimal")]
pub async fn get_providers_minimal(
data: web::Data<AppState>,
) -> Result<HttpResponse, ErrorResponse> {
pub async fn get_providers_minimal() -> Result<HttpResponse, ErrorResponse> {
// unauthorized - does not leak any sensitive information other than shown in the
// default login page anyway
match AuthProviderTemplate::get_all_json_template(&data).await? {
match AuthProviderTemplate::get_all_json_template().await? {
None => Ok(HttpResponse::Ok().insert_header(HEADER_JSON).body("[]")),
Some(tpl) => Ok(HttpResponse::Ok().insert_header(HEADER_JSON).body(tpl)),
}
Expand All @@ -268,7 +255,6 @@ pub async fn get_providers_minimal(
)]
#[put("/providers/{id}")]
pub async fn put_provider(
data: web::Data<AppState>,
id: web::Path<String>,
payload: Json<ProviderRequest>,
principal: ReqPrincipal,
Expand All @@ -282,7 +268,7 @@ pub async fn put_provider(
));
}

AuthProvider::update(&data, id.into_inner(), payload.into_inner()).await?;
AuthProvider::update(id.into_inner(), payload.into_inner()).await?;
Ok(HttpResponse::Ok().finish())
}

Expand All @@ -300,13 +286,12 @@ pub async fn put_provider(
)]
#[delete("/providers/{id}")]
pub async fn delete_provider(
data: web::Data<AppState>,
id: web::Path<String>,
principal: ReqPrincipal,
) -> Result<HttpResponse, ErrorResponse> {
principal.validate_admin_session()?;

AuthProvider::delete(&data, &id.into_inner()).await?;
AuthProvider::delete(&id.into_inner()).await?;
Ok(HttpResponse::Ok().finish())
}

Expand All @@ -326,13 +311,12 @@ pub async fn delete_provider(
)]
#[get("/providers/{id}/delete_safe")]
pub async fn get_provider_delete_safe(
data: web::Data<AppState>,
id: web::Path<String>,
principal: ReqPrincipal,
) -> Result<HttpResponse, ErrorResponse> {
principal.validate_admin_session()?;

let linked_users = AuthProvider::find_linked_users(&data, &id.into_inner()).await?;
let linked_users = AuthProvider::find_linked_users(&id.into_inner()).await?;
if linked_users.is_empty() {
Ok(HttpResponse::Ok().json(linked_users))
} else {
Expand All @@ -350,12 +334,9 @@ pub async fn get_provider_delete_safe(
),
)]
#[get("/providers/{id}/img")]
pub async fn get_provider_img(
data: web::Data<AppState>,
id: web::Path<String>,
) -> Result<HttpResponse, ErrorResponse> {
pub async fn get_provider_img(id: web::Path<String>) -> Result<HttpResponse, ErrorResponse> {
let id = id.into_inner();
let logo = Logo::find_cached(&data, &id, &LogoType::AuthProvider).await?;
let logo = Logo::find_cached(&id, &LogoType::AuthProvider).await?;

Ok(HttpResponse::Ok()
.insert_header((CONTENT_TYPE, logo.content_type))
Expand Down Expand Up @@ -383,7 +364,6 @@ pub async fn get_provider_img(
)]
#[put("/providers/{id}/img")]
pub async fn put_provider_img(
data: web::Data<AppState>,
id: web::Path<String>,
principal: ReqPrincipal,
mut payload: actix_multipart::Multipart,
Expand Down Expand Up @@ -417,7 +397,6 @@ pub async fn put_provider_img(

// content_type unwrap cannot panic -> checked above
Logo::upsert(
&data,
id.into_inner(),
buf,
content_type.unwrap(),
Expand Down Expand Up @@ -445,15 +424,14 @@ pub async fn put_provider_img(
)]
#[post("/providers/{id}/link")]
pub async fn post_provider_link(
data: web::Data<AppState>,
provider_id: web::Path<String>,
principal: ReqPrincipal,
payload: Json<ProviderLoginRequest>,
) -> Result<HttpResponse, ErrorResponse> {
principal.validate_session_auth()?;

let user_id = principal.user_id()?.to_string();
let user = User::find(&data, user_id).await?;
let user = User::find(user_id).await?;

// make sure the user is currently un-linked
if user.auth_provider_id.is_some() {
Expand All @@ -472,7 +450,7 @@ pub async fn post_provider_link(

// directly redirect to the provider login page
let (login_cookie, xsrf_token, location) =
AuthProviderCallback::login_start(&data, payload.into_inner()).await?;
AuthProviderCallback::login_start(payload.into_inner()).await?;

Ok(HttpResponse::Accepted()
.insert_header((LOCATION, location))
Expand Down
Loading

0 comments on commit 0578be3

Please sign in to comment.