use crate::{
common::{deserialize_ms, serialize_opt_ms},
AbuseType, Error,
};
use serde::{Deserialize, Serialize};
use std::{fmt, time::SystemTime};
#[derive(Debug)]
pub enum Entity {
User {
user_id: String,
},
Order {
user_id: String,
order_id: String,
},
Session {
user_id: String,
session_id: String,
},
Content {
user_id: String,
content_id: String,
},
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum EntityType {
User,
Order,
Session,
Content,
}
impl fmt::Display for Entity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Entity::User { user_id } => f.write_fmt(format_args!("users/{}", user_id)),
Entity::Order { user_id, order_id } => {
f.write_fmt(format_args!("users/{}/orders/{}", user_id, order_id))
}
Entity::Session {
user_id,
session_id,
} => f.write_fmt(format_args!("users/{}/sessions/{}", user_id, session_id)),
Entity::Content {
user_id,
content_id,
} => f.write_fmt(format_args!("users/{}/content/{}", user_id, content_id)),
}
}
}
#[derive(Debug, Serialize)]
pub struct DecisionRequest {
pub decision_id: String,
pub source: Source,
pub analyst: Option<String>,
#[serde(serialize_with = "serialize_opt_ms")]
pub time: Option<SystemTime>,
pub description: Option<String>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum Source {
ManualReview,
AutomatedRule,
Chargeback,
}
#[derive(Debug, Deserialize)]
pub struct Decision {
pub entity: EntityIdentifier,
pub decision: DecisionIdentifier,
#[serde(deserialize_with = "deserialize_ms")]
pub time: SystemTime,
}
#[derive(Debug, Deserialize)]
pub struct EntityIdentifier {
#[serde(rename = "type")]
pub entity_type: EntityType,
pub id: String,
}
#[derive(Debug, Deserialize)]
pub struct DecisionStatus {
pub decisions: Decisions,
}
#[derive(Debug, Deserialize)]
pub struct Decisions {
pub payment_abuse: Option<LatestDecision>,
pub promo_abuse: Option<LatestDecision>,
pub content_abuse: Option<LatestDecision>,
pub account_abuse: Option<LatestDecision>,
pub account_takeover: Option<LatestDecision>,
pub legacy: Option<LatestDecision>,
}
#[derive(Debug, Deserialize)]
pub struct LatestDecision {
pub decision: DecisionIdentifier,
pub webhook_succeeded: Option<bool>,
#[serde(deserialize_with = "deserialize_ms")]
pub time: SystemTime,
}
#[derive(Debug, Deserialize)]
pub struct DecisionIdentifier {
pub id: String,
}
#[derive(Debug, Deserialize)]
pub struct DecisionPage {
#[serde(rename = "data")]
pub decisions: Vec<DecisionData>,
pub has_more: bool,
pub schema: String,
pub total_results: u32,
}
#[derive(Debug, Deserialize)]
pub struct DecisionData {
pub id: String,
pub name: Option<String>,
pub description: Option<String>,
pub entity_type: EntityType,
pub abuse_type: AbuseType,
pub category: String,
#[serde(default)]
pub webhook_url: Option<String>,
#[serde(deserialize_with = "deserialize_ms")]
pub created_at: SystemTime,
#[serde(default)]
pub created_by: Option<String>,
#[serde(deserialize_with = "deserialize_ms")]
pub updated_at: SystemTime,
#[serde(default)]
pub updated_by: Option<String>,
}
#[derive(Deserialize)]
#[serde(untagged)]
pub(crate) enum DecisionResult<T> {
Error(Error),
Decision(T),
}
#[derive(Copy, Clone, Debug)]
pub enum ApiVersion {
V3,
}
impl fmt::Display for ApiVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ApiVersion::V3 => write!(f, "v3"),
}
}
}