Skip to content

Commit

Permalink
Implement schemars::JsonSchema for non-secret new types.
Browse files Browse the repository at this point in the history
Placed behind a `schemars` feature flag.
  • Loading branch information
gibbz00 committed Jun 28, 2024
1 parent daf4db6 commit e23e605
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 8 deletions.
10 changes: 9 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
[package]
name = "oauth2"
authors = ["Alex Crichton <[email protected]>", "Florin Lipan <[email protected]>", "David A. Ramos <[email protected]>"]
authors = [
"Alex Crichton <[email protected]>",
"Florin Lipan <[email protected]>",
"David A. Ramos <[email protected]>",
]
version = "5.0.0-alpha.4"
license = "MIT OR Apache-2.0"
description = "An extensible, strongly-typed implementation of OAuth2"
Expand All @@ -22,6 +26,7 @@ native-tls = ["reqwest/native-tls"]
reqwest-blocking = ["reqwest/blocking"]
rustls-tls = ["reqwest/rustls-tls"]
timing-resistant-secret-traits = []
schemars = ["dep:schemars"]

[[example]]
name = "github"
Expand Down Expand Up @@ -61,6 +66,9 @@ url = { version = "2.1", features = ["serde"] }
chrono = { version = "0.4.31", default-features = false, features = ["clock", "serde", "std", "wasmbind"] }
serde_path_to_error = "0.1.2"

# Feature: schemars
schemars = { version = "0.8", optional = true }

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2", features = ["js"] }

Expand Down
62 changes: 55 additions & 7 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ macro_rules! new_type {
}
) => {
$(#[$attr])*
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, ::serde::Serialize, ::serde::Deserialize)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct $name(
$(#[$type_attr])*
$type
Expand Down Expand Up @@ -344,13 +345,29 @@ macro_rules! new_url_type {
}
}
impl Eq for $name {}


#[cfg(feature = "schemars")]
impl schemars::JsonSchema for $name {
fn schema_name() -> String {
stringify!($name).to_owned()
}

fn schema_id() -> std::borrow::Cow<'static, str> {
std::borrow::Cow::Borrowed(concat!("oauth2::", stringify!($name)))
}

fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
// HELP(gibbz00): do we want to generate the schema for a URL or a String?
gen.subschema_for::<String>()
}
}
};
}

new_type![
/// Client identifier issued to the client during the registration process described by
/// [Section 2.2](https://tools.ietf.org/html/rfc6749#section-2.2).
#[derive(Deserialize, Serialize, Eq, Hash)]
ClientId(String)
];

Expand Down Expand Up @@ -385,19 +402,16 @@ new_url_type![
new_type![
/// Authorization endpoint response (grant) type defined in
/// [Section 3.1.1](https://tools.ietf.org/html/rfc6749#section-3.1.1).
#[derive(Deserialize, Serialize, Eq, Hash)]
ResponseType(String)
];
new_type![
/// Resource owner's username used directly as an authorization grant to obtain an access
/// token.
#[derive(Deserialize, Serialize, Eq, Hash)]
ResourceOwnerUsername(String)
];

new_type![
/// Access token scope, as defined by the authorization server.
#[derive(Deserialize, Serialize, Eq, Hash)]
Scope(String)
];
impl AsRef<str> for Scope {
Expand All @@ -409,7 +423,6 @@ impl AsRef<str> for Scope {
new_type![
/// Code Challenge Method used for [PKCE](https://tools.ietf.org/html/rfc7636) protection
/// via the `code_challenge_method` parameter.
#[derive(Deserialize, Serialize, Eq, Hash)]
PkceCodeChallengeMethod(String)
];
// This type intentionally does not implement Clone in order to make it difficult to reuse PKCE
Expand Down Expand Up @@ -614,7 +627,7 @@ new_secret_type![

#[cfg(test)]
mod tests {
use crate::{ClientSecret, CsrfToken, PkceCodeChallenge, PkceCodeVerifier};
use super::*;

#[test]
fn test_secret_conversion() {
Expand Down Expand Up @@ -662,4 +675,39 @@ mod tests {
"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
);
}

#[cfg(feature = "schemars")]
mod json_schema {
use schemars::schema_for;
use serde_json::json;

use super::*;

#[test]
fn generates_new_type_json_schema() {
let expected_schema = json!({
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ClientId",
"description": "Client identifier issued to the client during the registration process described by [Section 2.2](https://tools.ietf.org/html/rfc6749#section-2.2).",
"type": "string"
});

let schema = schema_for!(ClientId);
let actual_schema = serde_json::to_value(&schema).unwrap();
assert_eq!(expected_schema, actual_schema)
}

#[test]
fn generates_new_url_type_json_schema() {
let expected_schema = json!({
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "RedirectUrl",
"type": "string"
});

let schema = schema_for!(RedirectUrl);
let actual_schema = serde_json::to_value(&schema).unwrap();
assert_eq!(expected_schema, actual_schema);
}
}
}

0 comments on commit e23e605

Please sign in to comment.