Files
AstralRinth/src/models/oauth_clients.rs
Jackson Kruger 6cfd4637db 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
2023-10-30 09:14:38 -07:00

111 lines
3.0 KiB
Rust

use super::{
ids::{Base62Id, UserId},
pats::Scopes,
};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::database::models::oauth_client_authorization_item::OAuthClientAuthorization as DBOAuthClientAuthorization;
use crate::database::models::oauth_client_item::OAuthClient as DBOAuthClient;
use crate::database::models::oauth_client_item::OAuthRedirectUri as DBOAuthRedirectUri;
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(from = "Base62Id")]
#[serde(into = "Base62Id")]
pub struct OAuthClientId(pub u64);
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(from = "Base62Id")]
#[serde(into = "Base62Id")]
pub struct OAuthClientAuthorizationId(pub u64);
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(from = "Base62Id")]
#[serde(into = "Base62Id")]
pub struct OAuthRedirectUriId(pub u64);
#[derive(Deserialize, Serialize)]
pub struct OAuthRedirectUri {
pub id: OAuthRedirectUriId,
pub client_id: OAuthClientId,
pub uri: String,
}
#[derive(Serialize, Deserialize)]
pub struct OAuthClientCreationResult {
#[serde(flatten)]
pub client: OAuthClient,
pub client_secret: String,
}
#[derive(Deserialize, Serialize)]
pub struct OAuthClient {
pub id: OAuthClientId,
pub name: String,
pub icon_url: Option<String>,
// The maximum scopes the client can request for OAuth
pub max_scopes: Scopes,
// The valid URIs that can be redirected to during an authorization request
pub redirect_uris: Vec<OAuthRedirectUri>,
// The user that created (and thus controls) this client
pub created_by: UserId,
}
#[derive(Deserialize, Serialize)]
pub struct OAuthClientAuthorization {
pub id: OAuthClientAuthorizationId,
pub app_id: OAuthClientId,
pub user_id: UserId,
pub scopes: Scopes,
pub created: DateTime<Utc>,
}
#[derive(Deserialize, Serialize)]
pub struct GetOAuthClientsRequest {
pub ids: Vec<OAuthClientId>,
}
#[derive(Deserialize, Serialize)]
pub struct DeleteOAuthClientQueryParam {
pub client_id: OAuthClientId,
}
impl From<DBOAuthClient> for OAuthClient {
fn from(value: DBOAuthClient) -> Self {
Self {
id: value.id.into(),
name: value.name,
icon_url: value.icon_url,
max_scopes: value.max_scopes,
redirect_uris: value.redirect_uris.into_iter().map(|r| r.into()).collect(),
created_by: value.created_by.into(),
}
}
}
impl From<DBOAuthRedirectUri> for OAuthRedirectUri {
fn from(value: DBOAuthRedirectUri) -> Self {
Self {
id: value.id.into(),
client_id: value.client_id.into(),
uri: value.uri,
}
}
}
impl From<DBOAuthClientAuthorization> for OAuthClientAuthorization {
fn from(value: DBOAuthClientAuthorization) -> Self {
Self {
id: value.id.into(),
app_id: value.client_id.into(),
user_id: value.user_id.into(),
scopes: value.scopes,
created: value.created,
}
}
}