You've already forked AstralRinth
forked from didirus/AstralRinth
OAuth 2.0 Authorization Server [MOD-559] (#733)
* WIP end-of-day push * Authorize endpoint, accept endpoints, DB stuff for oauth clients, their redirects, and client authorizations * OAuth Client create route * Get user clients * Client delete * Edit oauth client * Include redirects in edit client route * Database stuff for tokens * Reorg oauth stuff out of auth/flows and into its own module * Impl OAuth get access token endpoint * Accept oauth access tokens as auth and update through AuthQueue * User OAuth authorization management routes * Forgot to actually add the routes lol * Bit o cleanup * Happy path test for OAuth and minor fixes for things it found * Add dummy data oauth client (and detect/handle dummy data version changes) * More tests * Another test * More tests and reject endpoint * Test oauth client and authorization management routes * cargo sqlx prepare * dead code warning * Auto clippy fixes * Uri refactoring * minor name improvement * Don't compile-time check the test sqlx queries * Trying to fix db concurrency problem to get tests to pass * Try fix from test PR * Fixes for updated sqlx * Prevent restricted scopes from being requested or issued * Get OAuth client(s) * Remove joined oauth client info from authorization returns * Add default conversion to OAuthError::error so we can use ? * Rework routes * Consolidate scopes into SESSION_ACCESS * Cargo sqlx prepare * Parse to OAuthClientId automatically through serde and actix * Cargo clippy * Remove validation requiring 1 redirect URI on oauth client creation * Use serde(flatten) on OAuthClientCreationResult
This commit is contained in:
126
src/database/models/oauth_client_authorization_item.rs
Normal file
126
src/database/models/oauth_client_authorization_item.rs
Normal file
@@ -0,0 +1,126 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use itertools::Itertools;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::models::pats::Scopes;
|
||||
|
||||
use super::{DatabaseError, OAuthClientAuthorizationId, OAuthClientId, UserId};
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone, Debug)]
|
||||
pub struct OAuthClientAuthorization {
|
||||
pub id: OAuthClientAuthorizationId,
|
||||
pub client_id: OAuthClientId,
|
||||
pub user_id: UserId,
|
||||
pub scopes: Scopes,
|
||||
pub created: DateTime<Utc>,
|
||||
}
|
||||
|
||||
struct AuthorizationQueryResult {
|
||||
id: i64,
|
||||
client_id: i64,
|
||||
user_id: i64,
|
||||
scopes: i64,
|
||||
created: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl From<AuthorizationQueryResult> for OAuthClientAuthorization {
|
||||
fn from(value: AuthorizationQueryResult) -> Self {
|
||||
OAuthClientAuthorization {
|
||||
id: OAuthClientAuthorizationId(value.id),
|
||||
client_id: OAuthClientId(value.client_id),
|
||||
user_id: UserId(value.user_id),
|
||||
scopes: Scopes::from_postgres(value.scopes),
|
||||
created: value.created,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OAuthClientAuthorization {
|
||||
pub async fn get(
|
||||
client_id: OAuthClientId,
|
||||
user_id: UserId,
|
||||
exec: impl sqlx::Executor<'_, Database = sqlx::Postgres>,
|
||||
) -> Result<Option<OAuthClientAuthorization>, DatabaseError> {
|
||||
let value = sqlx::query_as!(
|
||||
AuthorizationQueryResult,
|
||||
"
|
||||
SELECT id, client_id, user_id, scopes, created
|
||||
FROM oauth_client_authorizations
|
||||
WHERE client_id=$1 AND user_id=$2
|
||||
",
|
||||
client_id.0,
|
||||
user_id.0,
|
||||
)
|
||||
.fetch_optional(exec)
|
||||
.await?;
|
||||
|
||||
Ok(value.map(|r| r.into()))
|
||||
}
|
||||
|
||||
pub async fn get_all_for_user(
|
||||
user_id: UserId,
|
||||
exec: impl sqlx::Executor<'_, Database = sqlx::Postgres>,
|
||||
) -> Result<Vec<OAuthClientAuthorization>, DatabaseError> {
|
||||
let results = sqlx::query_as!(
|
||||
AuthorizationQueryResult,
|
||||
"
|
||||
SELECT id, client_id, user_id, scopes, created
|
||||
FROM oauth_client_authorizations
|
||||
WHERE user_id=$1
|
||||
",
|
||||
user_id.0
|
||||
)
|
||||
.fetch_all(exec)
|
||||
.await?;
|
||||
|
||||
Ok(results.into_iter().map(|r| r.into()).collect_vec())
|
||||
}
|
||||
|
||||
pub async fn upsert(
|
||||
id: OAuthClientAuthorizationId,
|
||||
client_id: OAuthClientId,
|
||||
user_id: UserId,
|
||||
scopes: Scopes,
|
||||
transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
) -> Result<(), DatabaseError> {
|
||||
sqlx::query!(
|
||||
"
|
||||
INSERT INTO oauth_client_authorizations (
|
||||
id, client_id, user_id, scopes
|
||||
)
|
||||
VALUES (
|
||||
$1, $2, $3, $4
|
||||
)
|
||||
ON CONFLICT (id)
|
||||
DO UPDATE SET scopes = EXCLUDED.scopes
|
||||
",
|
||||
id.0,
|
||||
client_id.0,
|
||||
user_id.0,
|
||||
scopes.bits() as i64,
|
||||
)
|
||||
.execute(&mut **transaction)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn remove(
|
||||
client_id: OAuthClientId,
|
||||
user_id: UserId,
|
||||
exec: impl sqlx::Executor<'_, Database = sqlx::Postgres>,
|
||||
) -> Result<(), DatabaseError> {
|
||||
sqlx::query!(
|
||||
"
|
||||
DELETE FROM oauth_client_authorizations
|
||||
WHERE client_id=$1 AND user_id=$2
|
||||
",
|
||||
client_id.0,
|
||||
user_id.0
|
||||
)
|
||||
.execute(exec)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user