about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--kittybox-rs/Cargo.lock1
-rw-r--r--kittybox-rs/indieauth/Cargo.toml2
-rw-r--r--kittybox-rs/indieauth/src/lib.rs57
-rw-r--r--kittybox-rs/indieauth/src/pkce.rs4
-rw-r--r--kittybox-rs/indieauth/src/scopes.rs2
5 files changed, 51 insertions, 15 deletions
diff --git a/kittybox-rs/Cargo.lock b/kittybox-rs/Cargo.lock
index f2caa77..b44fa6f 100644
--- a/kittybox-rs/Cargo.lock
+++ b/kittybox-rs/Cargo.lock
@@ -1548,6 +1548,7 @@ dependencies = [
  "rand 0.8.5",
  "serde",
  "serde_json",
+ "serde_urlencoded",
  "sha2",
  "url",
 ]
diff --git a/kittybox-rs/indieauth/Cargo.toml b/kittybox-rs/indieauth/Cargo.toml
index 222d706..80511f9 100644
--- a/kittybox-rs/indieauth/Cargo.toml
+++ b/kittybox-rs/indieauth/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
 
 [dev-dependencies]
 serde_json = "^1.0.64"       # A JSON serialization file format
-
+serde_urlencoded = "^0.7.0"  # `x-www-form-urlencoded` meets Serde
 [dependencies]
 rand = "^0.8.5"              # Utilities for random number generation
 data-encoding = "^2.3.2"     # Efficient and customizable data-encoding functions like base64, base32, and hex
diff --git a/kittybox-rs/indieauth/src/lib.rs b/kittybox-rs/indieauth/src/lib.rs
index 23b3923..242317d 100644
--- a/kittybox-rs/indieauth/src/lib.rs
+++ b/kittybox-rs/indieauth/src/lib.rs
@@ -61,7 +61,8 @@ pub struct Metadata {
     pub revocation_endpoint_auth_methods_supported: Option<Vec<RevocationEndpointAuthMethod>>,
     // Note: Scopes isn't used here because this field should be
     // serialized as a list, not as a string
-    pub scopes_supported: Vec<Scope>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub scopes_supported: Option<Vec<Scope>>,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub response_types_supported: Option<Vec<ResponseType>>,
     #[serde(skip_serializing_if = "Option::is_none")]
@@ -112,24 +113,32 @@ pub struct AuthorizationRequest {
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
-struct AuthorizationResponse {
+pub struct AuthorizationResponse {
     pub code: String,
     pub state: State,
-    iss: Url
+    pub iss: Url
 }
 
-#[derive(Debug, Clone, Serialize, Deserialize)]
-struct GrantRequest {
-    grant_type: GrantType,
-    code: String,
-    client_id: Url,
-    redirect_uri: Url,
-    code_verifier: PKCEVerifier
+#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
+#[serde(tag = "grant_type")]
+#[serde(rename_all = "snake_case")]
+pub enum GrantRequest {
+    AuthorizationCode {
+        code: String,
+        client_id: Url,
+        redirect_uri: Url,
+        code_verifier: PKCEVerifier
+    },
+    RefreshToken {
+        refresh_token: String,
+        client_id: url::Url,
+        scope: Option<Scopes>
+    }
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
 #[serde(untagged)]
-enum GrantResponse {
+pub enum GrantResponse {
     AccessToken {
         me: Url,
         #[serde(skip_serializing_if = "Option::is_none")]
@@ -254,4 +263,30 @@ mod tests {
             json!({"error": "insufficient_scope"})
         );
     }
+
+    #[test]
+    fn test_serialize_deserialize_grant_request() {
+        let authorization_code: GrantRequest = GrantRequest::AuthorizationCode {
+            client_id: "https://kittybox.fireburn.ru/".parse().unwrap(),
+            redirect_uri: "https://kittybox.fireburn.ru/.kittybox/login/redirect".parse().unwrap(),
+            code_verifier: PKCEVerifier("helloworld".to_string()),
+            code: "hithere".to_owned()
+        };
+        let serialized = serde_urlencoded::to_string(&[
+            ("grant_type", "authorization_code"),
+            ("code", "hithere"),
+            ("client_id", "https://kittybox.fireburn.ru/"),
+            ("redirect_uri", "https://kittybox.fireburn.ru/.kittybox/login/redirect"),
+            ("code_verifier", "helloworld"),
+        ]).unwrap();
+
+        let deserialized = serde_urlencoded::from_str(&serialized).unwrap();
+
+        assert_eq!(authorization_code, deserialized);
+
+        assert_eq!(
+            serialized,
+            serde_urlencoded::to_string(authorization_code).unwrap()
+        )
+    }
 }
diff --git a/kittybox-rs/indieauth/src/pkce.rs b/kittybox-rs/indieauth/src/pkce.rs
index a0bc291..1d3c58f 100644
--- a/kittybox-rs/indieauth/src/pkce.rs
+++ b/kittybox-rs/indieauth/src/pkce.rs
@@ -9,8 +9,8 @@ pub enum PKCEMethod {
     Plain
 }
 
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct PKCEVerifier(String);
+#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
+pub struct PKCEVerifier(pub(super) String);
 
 impl AsRef<str> for PKCEVerifier {
     fn as_ref(&self) -> &str {
diff --git a/kittybox-rs/indieauth/src/scopes.rs b/kittybox-rs/indieauth/src/scopes.rs
index bc57265..e803dca 100644
--- a/kittybox-rs/indieauth/src/scopes.rs
+++ b/kittybox-rs/indieauth/src/scopes.rs
@@ -80,7 +80,7 @@ impl From<&str> for Scope {
         }
     }
 }
-#[derive(Debug, Clone)]
+#[derive(PartialEq, Eq, Debug, Clone)]
 pub struct Scopes(Vec<Scope>);
 impl Scopes {
     pub fn new(scopes: Vec<Scope>) -> Self {