use serde::{Deserialize, Serialize};
use crate::common::{GrantId, Provider};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum GrantStatus {
Valid,
Invalid,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Grant {
pub id: GrantId,
pub provider: Provider,
#[serde(skip_serializing_if = "Option::is_none")]
pub grant_status: Option<GrantStatus>,
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scope: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user_timezone: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub provider_user_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ip: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user_agent: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub settings: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Value>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CreateGrantRequest {
pub provider: Provider,
#[serde(skip_serializing_if = "Option::is_none")]
pub settings: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scope: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Value>,
}
impl CreateGrantRequest {
pub fn builder(provider: Provider) -> CreateGrantRequestBuilder {
CreateGrantRequestBuilder::new(provider)
}
}
#[derive(Debug, Clone)]
pub struct CreateGrantRequestBuilder {
provider: Provider,
settings: Option<serde_json::Value>,
scope: Option<Vec<String>>,
state: Option<String>,
metadata: Option<serde_json::Value>,
}
impl CreateGrantRequestBuilder {
pub fn new(provider: Provider) -> Self {
Self {
provider,
settings: None,
scope: None,
state: None,
metadata: None,
}
}
pub fn settings(mut self, settings: serde_json::Value) -> Self {
self.settings = Some(settings);
self
}
pub fn scope(mut self, scope: Vec<String>) -> Self {
self.scope = Some(scope);
self
}
pub fn state(mut self, state: impl Into<String>) -> Self {
self.state = Some(state.into());
self
}
pub fn metadata(mut self, metadata: serde_json::Value) -> Self {
self.metadata = Some(metadata);
self
}
pub fn build(self) -> CreateGrantRequest {
CreateGrantRequest {
provider: self.provider,
settings: self.settings,
scope: self.scope,
state: self.state,
metadata: self.metadata,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct UpdateGrantRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub settings: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scope: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Value>,
}
impl UpdateGrantRequest {
pub fn builder() -> UpdateGrantRequestBuilder {
UpdateGrantRequestBuilder::default()
}
}
#[derive(Debug, Clone, Default)]
pub struct UpdateGrantRequestBuilder {
settings: Option<serde_json::Value>,
scope: Option<Vec<String>>,
metadata: Option<serde_json::Value>,
}
impl UpdateGrantRequestBuilder {
pub fn settings(mut self, settings: serde_json::Value) -> Self {
self.settings = Some(settings);
self
}
pub fn scope(mut self, scope: Vec<String>) -> Self {
self.scope = Some(scope);
self
}
pub fn metadata(mut self, metadata: serde_json::Value) -> Self {
self.metadata = Some(metadata);
self
}
pub fn build(self) -> UpdateGrantRequest {
UpdateGrantRequest {
settings: self.settings,
scope: self.scope,
metadata: self.metadata,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_grant_serialization() {
let grant = Grant {
id: GrantId::new("grant_123"),
provider: Provider::Google,
grant_status: Some(GrantStatus::Valid),
email: Some("user@example.com".to_string()),
scope: Some(vec![
"https://www.googleapis.com/auth/gmail.readonly".to_string()
]),
user_timezone: None,
created_at: Some(1234567890),
updated_at: Some(1234567890),
provider_user_id: None,
ip: None,
state: None,
user_agent: None,
settings: None,
metadata: None,
};
let json = serde_json::to_string(&grant).unwrap();
assert!(json.contains("grant_123"));
assert!(json.contains("google"));
assert!(json.contains("user@example.com"));
}
#[test]
fn test_grant_deserialization() {
let json = r#"{
"id": "grant_123",
"provider": "google",
"grant_status": "valid",
"email": "user@example.com",
"scope": ["https://www.googleapis.com/auth/gmail.readonly"],
"created_at": 1234567890,
"updated_at": 1234567890
}"#;
let grant: Grant = serde_json::from_str(json).unwrap();
assert_eq!(grant.id.as_str(), "grant_123");
assert_eq!(grant.provider, Provider::Google);
assert_eq!(grant.grant_status, Some(GrantStatus::Valid));
assert_eq!(grant.email, Some("user@example.com".to_string()));
}
#[test]
fn test_grant_status_serialization() {
assert_eq!(
serde_json::to_string(&GrantStatus::Valid).unwrap(),
r#""valid""#
);
assert_eq!(
serde_json::to_string(&GrantStatus::Invalid).unwrap(),
r#""invalid""#
);
}
#[test]
fn test_create_grant_request_builder() {
let request = CreateGrantRequest::builder(Provider::Google)
.scope(vec![
"https://www.googleapis.com/auth/gmail.readonly".to_string()
])
.state("test_state")
.build();
assert_eq!(request.provider, Provider::Google);
assert!(request.scope.is_some());
assert_eq!(request.state, Some("test_state".to_string()));
assert!(request.settings.is_none());
assert!(request.metadata.is_none());
}
#[test]
fn test_create_grant_request_with_metadata() {
let metadata = serde_json::json!({"team": "engineering"});
let request = CreateGrantRequest::builder(Provider::Microsoft)
.metadata(metadata.clone())
.build();
assert_eq!(request.provider, Provider::Microsoft);
assert_eq!(request.metadata, Some(metadata));
}
#[test]
fn test_update_grant_request_builder() {
let metadata = serde_json::json!({"updated": true});
let request = UpdateGrantRequest::builder()
.metadata(metadata.clone())
.scope(vec!["new_scope".to_string()])
.build();
assert_eq!(request.metadata, Some(metadata));
assert_eq!(request.scope, Some(vec!["new_scope".to_string()]));
assert!(request.settings.is_none());
}
#[test]
fn test_update_grant_request_default() {
let request = UpdateGrantRequest::default();
assert!(request.settings.is_none());
assert!(request.scope.is_none());
assert!(request.metadata.is_none());
}
}