Skip to content

Commit e23e605

Browse files
committed
Implement schemars::JsonSchema for non-secret new types.
Placed behind a `schemars` feature flag.
1 parent daf4db6 commit e23e605

File tree

2 files changed

+64
-8
lines changed

2 files changed

+64
-8
lines changed

Cargo.toml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
[package]
22
name = "oauth2"
3-
authors = ["Alex Crichton <[email protected]>", "Florin Lipan <[email protected]>", "David A. Ramos <[email protected]>"]
3+
authors = [
4+
"Alex Crichton <[email protected]>",
5+
"Florin Lipan <[email protected]>",
6+
"David A. Ramos <[email protected]>",
7+
]
48
version = "5.0.0-alpha.4"
59
license = "MIT OR Apache-2.0"
610
description = "An extensible, strongly-typed implementation of OAuth2"
@@ -22,6 +26,7 @@ native-tls = ["reqwest/native-tls"]
2226
reqwest-blocking = ["reqwest/blocking"]
2327
rustls-tls = ["reqwest/rustls-tls"]
2428
timing-resistant-secret-traits = []
29+
schemars = ["dep:schemars"]
2530

2631
[[example]]
2732
name = "github"
@@ -61,6 +66,9 @@ url = { version = "2.1", features = ["serde"] }
6166
chrono = { version = "0.4.31", default-features = false, features = ["clock", "serde", "std", "wasmbind"] }
6267
serde_path_to_error = "0.1.2"
6368

69+
# Feature: schemars
70+
schemars = { version = "0.8", optional = true }
71+
6472
[target.'cfg(target_arch = "wasm32")'.dependencies]
6573
getrandom = { version = "0.2", features = ["js"] }
6674

src/types.rs

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ macro_rules! new_type {
7777
}
7878
) => {
7979
$(#[$attr])*
80-
#[derive(Clone, Debug, PartialEq)]
80+
#[derive(Clone, Debug, PartialEq, Eq, Hash, ::serde::Serialize, ::serde::Deserialize)]
81+
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
8182
pub struct $name(
8283
$(#[$type_attr])*
8384
$type
@@ -344,13 +345,29 @@ macro_rules! new_url_type {
344345
}
345346
}
346347
impl Eq for $name {}
348+
349+
350+
#[cfg(feature = "schemars")]
351+
impl schemars::JsonSchema for $name {
352+
fn schema_name() -> String {
353+
stringify!($name).to_owned()
354+
}
355+
356+
fn schema_id() -> std::borrow::Cow<'static, str> {
357+
std::borrow::Cow::Borrowed(concat!("oauth2::", stringify!($name)))
358+
}
359+
360+
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
361+
// HELP(gibbz00): do we want to generate the schema for a URL or a String?
362+
gen.subschema_for::<String>()
363+
}
364+
}
347365
};
348366
}
349367

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

@@ -385,19 +402,16 @@ new_url_type![
385402
new_type![
386403
/// Authorization endpoint response (grant) type defined in
387404
/// [Section 3.1.1](https://tools.ietf.org/html/rfc6749#section-3.1.1).
388-
#[derive(Deserialize, Serialize, Eq, Hash)]
389405
ResponseType(String)
390406
];
391407
new_type![
392408
/// Resource owner's username used directly as an authorization grant to obtain an access
393409
/// token.
394-
#[derive(Deserialize, Serialize, Eq, Hash)]
395410
ResourceOwnerUsername(String)
396411
];
397412

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

615628
#[cfg(test)]
616629
mod tests {
617-
use crate::{ClientSecret, CsrfToken, PkceCodeChallenge, PkceCodeVerifier};
630+
use super::*;
618631

619632
#[test]
620633
fn test_secret_conversion() {
@@ -662,4 +675,39 @@ mod tests {
662675
"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
663676
);
664677
}
678+
679+
#[cfg(feature = "schemars")]
680+
mod json_schema {
681+
use schemars::schema_for;
682+
use serde_json::json;
683+
684+
use super::*;
685+
686+
#[test]
687+
fn generates_new_type_json_schema() {
688+
let expected_schema = json!({
689+
"$schema": "http://json-schema.org/draft-07/schema#",
690+
"title": "ClientId",
691+
"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).",
692+
"type": "string"
693+
});
694+
695+
let schema = schema_for!(ClientId);
696+
let actual_schema = serde_json::to_value(&schema).unwrap();
697+
assert_eq!(expected_schema, actual_schema)
698+
}
699+
700+
#[test]
701+
fn generates_new_url_type_json_schema() {
702+
let expected_schema = json!({
703+
"$schema": "http://json-schema.org/draft-07/schema#",
704+
"title": "RedirectUrl",
705+
"type": "string"
706+
});
707+
708+
let schema = schema_for!(RedirectUrl);
709+
let actual_schema = serde_json::to_value(&schema).unwrap();
710+
assert_eq!(expected_schema, actual_schema);
711+
}
712+
}
665713
}

0 commit comments

Comments
 (0)