use std::fmt;
use serde::{Deserialize, Serialize};
use crate::types::{Kind, Object, SurrealValue, Value, kind};
#[derive(Debug)]
pub struct Signup;
#[derive(Debug)]
pub struct Signin;
pub trait Credentials<Action>: SurrealValue {}
#[derive(Debug, Clone, SurrealValue)]
#[surreal(crate = "crate::types")]
pub struct Root {
#[surreal(rename = "user")]
pub username: String,
#[surreal(rename = "pass")]
pub password: String,
}
impl Credentials<Signin> for Root {}
#[derive(Debug, Clone, SurrealValue)]
#[surreal(crate = "crate::types")]
pub struct Namespace {
#[surreal(rename = "ns")]
pub namespace: String,
#[surreal(rename = "user")]
pub username: String,
#[surreal(rename = "pass")]
pub password: String,
}
impl Credentials<Signin> for Namespace {}
#[derive(Debug, Clone, SurrealValue)]
#[surreal(crate = "crate::types")]
pub struct Database {
#[surreal(rename = "ns")]
pub namespace: String,
#[surreal(rename = "db")]
pub database: String,
#[surreal(rename = "user")]
pub username: String,
#[surreal(rename = "pass")]
pub password: String,
}
impl Credentials<Signin> for Database {}
#[derive(Debug)]
pub struct Record<P: SurrealValue> {
pub namespace: String,
pub database: String,
pub access: String,
pub params: P,
}
impl<P: SurrealValue> SurrealValue for Record<P> {
fn kind_of() -> Kind {
kind!({ ns: string, db: string, ac: string, params: any })
}
fn into_value(self) -> Value {
let mut obj = Object::new();
obj.insert("ns".to_string(), Value::String(self.namespace));
obj.insert("db".to_string(), Value::String(self.database));
obj.insert("ac".to_string(), Value::String(self.access));
if let Value::Object(params_obj) = self.params.into_value() {
for (key, value) in params_obj {
obj.insert(key, value);
}
}
Value::Object(obj)
}
fn from_value(value: Value) -> Result<Self, crate::Error> {
if let Value::Object(mut obj) = value {
let namespace = obj
.remove("ns")
.and_then(|v| {
if let Value::String(s) = v {
Some(s)
} else {
None
}
})
.ok_or_else(|| crate::Error::internal("Missing 'ns' field".to_string()))?;
let database = obj
.remove("db")
.and_then(|v| {
if let Value::String(s) = v {
Some(s)
} else {
None
}
})
.ok_or_else(|| crate::Error::internal("Missing 'db' field".to_string()))?;
let access = obj
.remove("ac")
.and_then(|v| {
if let Value::String(s) = v {
Some(s)
} else {
None
}
})
.ok_or_else(|| crate::Error::internal("Missing 'ac' field".to_string()))?;
let params = P::from_value(Value::Object(obj))?;
Ok(Record {
namespace,
database,
access,
params,
})
} else {
Err(crate::Error::internal("Expected an object for Record".to_string()))
}
}
}
impl<T, P> Credentials<T> for Record<P> where P: SurrealValue {}
#[derive(Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub struct Token {
pub access: AccessToken,
pub refresh: Option<RefreshToken>,
}
impl SurrealValue for Token {
fn kind_of() -> Kind {
kind!(string | { access: string, refresh: string })
}
fn into_value(self) -> Value {
match self.refresh {
Some(refresh) => {
let mut obj = Object::new();
obj.insert("access".to_string(), self.access.into_value());
obj.insert("refresh".to_string(), refresh.into_value());
Value::Object(obj)
}
None => self.access.into_value(),
}
}
fn from_value(value: Value) -> Result<Self, crate::Error> {
match value {
Value::String(string) => Ok(Token::from(string)),
value => {
let mut obj = Object::from_value(value)?;
let access = AccessToken::from_value(obj.remove("access").unwrap_or_default())?;
let refresh = RefreshToken::from_value(obj.remove("refresh").unwrap_or_default())?;
Ok(Token::from((access, refresh)))
}
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, SurrealValue)]
#[surreal(crate = "crate::types")]
pub struct AccessToken(pub(crate) SecureToken);
impl AccessToken {
pub fn as_insecure_token(&self) -> &str {
&self.0.0
}
pub fn into_insecure_token(self) -> String {
self.0.0
}
}
#[derive(Debug, Serialize, Deserialize, SurrealValue)]
#[surreal(crate = "crate::types")]
pub struct RefreshToken(pub(crate) SecureToken);
impl RefreshToken {
pub fn as_insecure_token(&self) -> &str {
&self.0.0
}
pub fn into_insecure_token(self) -> String {
self.0.0
}
}
#[derive(Clone, Serialize, Deserialize, SurrealValue)]
#[surreal(crate = "crate::types")]
pub(crate) struct SecureToken(pub(crate) String);
impl fmt::Debug for SecureToken {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "REDACTED")
}
}
impl From<AccessToken> for Token {
fn from(access: AccessToken) -> Self {
Self {
access,
refresh: None,
}
}
}
impl From<(AccessToken, RefreshToken)> for Token {
fn from(token: (AccessToken, RefreshToken)) -> Self {
Self {
access: token.0,
refresh: Some(token.1),
}
}
}
impl From<(AccessToken, Option<RefreshToken>)> for Token {
fn from(token: (AccessToken, Option<RefreshToken>)) -> Self {
Self {
access: token.0,
refresh: token.1,
}
}
}
impl From<String> for Token {
fn from(token: String) -> Self {
Self {
access: AccessToken(SecureToken(token)),
refresh: None,
}
}
}
impl<'a> From<&'a String> for Token {
fn from(token: &'a String) -> Self {
Self {
access: AccessToken(SecureToken(token.to_owned())),
refresh: None,
}
}
}
impl<'a> From<&'a str> for Token {
fn from(token: &'a str) -> Self {
Self {
access: AccessToken(SecureToken(token.to_owned())),
refresh: None,
}
}
}
impl From<String> for AccessToken {
fn from(token: String) -> Self {
Self(SecureToken(token))
}
}
impl<'a> From<&'a String> for AccessToken {
fn from(token: &'a String) -> Self {
Self(SecureToken(token.to_owned()))
}
}
impl<'a> From<&'a str> for AccessToken {
fn from(token: &'a str) -> Self {
Self(SecureToken(token.to_owned()))
}
}
impl From<String> for RefreshToken {
fn from(token: String) -> Self {
Self(SecureToken(token))
}
}
impl<'a> From<&'a String> for RefreshToken {
fn from(token: &'a String) -> Self {
Self(SecureToken(token.to_owned()))
}
}
impl<'a> From<&'a str> for RefreshToken {
fn from(token: &'a str) -> Self {
Self(SecureToken(token.to_owned()))
}
}
impl From<RefreshToken> for SecureToken {
fn from(token: RefreshToken) -> Self {
token.0
}
}