-
-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #71 from sebadob/impl-rauthy-db-version-check
DB version check fully working
- Loading branch information
Showing
6 changed files
with
163 additions
and
8 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
use crate::app_state::DbPool; | ||
use rauthy_common::constants::RAUTHY_VERSION; | ||
use rauthy_common::error_response::ErrorResponse; | ||
use semver::Version; | ||
use serde::{Deserialize, Serialize}; | ||
use sqlx::query; | ||
use std::str::FromStr; | ||
use tracing::{debug, warn}; | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
pub struct DbVersion { | ||
pub version: Version, | ||
} | ||
|
||
impl DbVersion { | ||
pub async fn find(db: &DbPool) -> Option<Self> { | ||
let res = query!("select data from config where id = 'db_version'") | ||
.fetch_optional(db) | ||
.await | ||
.ok()?; | ||
match res { | ||
Some(res) => { | ||
let data = res | ||
.data | ||
.expect("to get 'data' back from the AppVersion query"); | ||
bincode::deserialize::<Self>(&data).ok() | ||
} | ||
None => None, | ||
} | ||
} | ||
|
||
pub async fn update(db: &DbPool, db_version: Option<Version>) -> Result<(), ErrorResponse> { | ||
let app_version = Self::app_version(); | ||
if Some(&app_version) != db_version.as_ref() { | ||
let slf = Self { | ||
version: app_version, | ||
}; | ||
let data = bincode::serialize(&slf)?; | ||
|
||
#[cfg(feature = "sqlite")] | ||
let q = query!( | ||
"insert or replace into config (id, data) values ('db_version', $1)", | ||
data, | ||
); | ||
#[cfg(not(feature = "sqlite"))] | ||
let q = query!( | ||
r#"insert into config (id, data) values ('db_version', $1) | ||
on conflict(id) do update set data = $1"#, | ||
data, | ||
); | ||
q.execute(db).await?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
pub async fn check_app_version(db: &DbPool) -> Result<Option<Version>, ErrorResponse> { | ||
let app_version = Self::app_version(); | ||
debug!("Current Rauthy Version: {:?}", app_version); | ||
|
||
// check DB version for compatibility | ||
let db_version = match Self::find(db).await { | ||
None => { | ||
debug!(" No Current DB Version found"); | ||
// check if the DB is completely new | ||
let db_exists = query!("select id from config limit 1").fetch_one(db).await; | ||
if db_exists.is_ok() { | ||
Self::is_db_compatible(db, &app_version, None).await?; | ||
} | ||
|
||
None | ||
} | ||
Some(db_version) => { | ||
debug!("Current DB Version: {:?}", db_version); | ||
Self::is_db_compatible(db, &app_version, Some(&db_version.version)).await?; | ||
|
||
Some(db_version.version) | ||
} | ||
}; | ||
|
||
Ok(db_version) | ||
} | ||
|
||
//github.com/ Checks if we can use an existing (possibly older) db with this version of rauthy, or if | ||
//github.com/ the user may need to take action beforehand. | ||
async fn is_db_compatible( | ||
db: &DbPool, | ||
app_version: &Version, | ||
db_version: Option<&Version>, | ||
) -> Result<(), ErrorResponse> { | ||
// this check panics on purpose and it is there to never forget to adjust this | ||
// version check before doing any major or minor release | ||
if app_version.major != 0 || app_version.minor != 16 { | ||
panic!( | ||
"\nDbVersion::check_app_version needs adjustment for the new RAUTHY_VERSION: {}", | ||
RAUTHY_VERSION | ||
); | ||
} | ||
|
||
// warn on prerelease usage | ||
if !app_version.pre.is_empty() { | ||
warn!("!!! Caution: you are using a prerelease version !!!"); | ||
} | ||
|
||
// check for the lowest DB version we can use with this App Version | ||
if let Some(db_version) = db_version { | ||
if db_version.major != 0 || db_version.minor < 15 || db_version.minor > 16 { | ||
panic!( | ||
"\nRauthy {} needs at least a DB version v0.15 and max v0.16", | ||
app_version | ||
); | ||
} | ||
|
||
return Ok(()); | ||
} | ||
|
||
// check the DB version in another way if we did not find an existing DB version | ||
|
||
// the passkeys table was introduced with v0.15.0 | ||
let passkeys_exist = query!("select user_id from passkeys limit 1") | ||
.fetch_one(db) | ||
.await; | ||
if passkeys_exist.is_err() { | ||
panic!("\nYou need to start at least rauthy v0.15 before you can upgrade"); | ||
} | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
impl DbVersion { | ||
pub fn app_version() -> Version { | ||
Version::from_str(RAUTHY_VERSION).expect("bad format for RAUTHY_VERSION") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters