2024-03-08 17:03:49 +01:00
|
|
|
use std::{convert::Infallible, fmt::Display, str::FromStr};
|
|
|
|
|
|
|
|
use crate::{store::Sequence, Item, Store};
|
2024-03-08 17:05:58 +01:00
|
|
|
use rand::seq::SliceRandom;
|
2024-03-08 17:03:49 +01:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
2024-03-08 19:49:40 +01:00
|
|
|
pub const ALPHABET: &str = "qwertzuiopasdfghjklyxcvbnmQWERTZUIOPASDFGHJKLYXCVBNM";
|
|
|
|
pub const TOK_LEN: usize = 40;
|
|
|
|
pub const ID_LEN: usize = 20;
|
2024-03-08 17:03:49 +01:00
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
|
|
|
|
pub struct Client {
|
|
|
|
#[serde(flatten)]
|
|
|
|
id: Id,
|
|
|
|
#[serde(flatten)]
|
|
|
|
token: Token,
|
|
|
|
last: Sequence,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Client {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
id: Id::new(),
|
|
|
|
token: Token::new(),
|
|
|
|
last: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(debug_assertions)]
|
|
|
|
#[allow(unused)]
|
|
|
|
pub(crate) fn new_debug() -> Self {
|
|
|
|
Self {
|
|
|
|
id: Id::from_str("myid").unwrap(),
|
|
|
|
token: Token::from_str("mytok").unwrap(),
|
|
|
|
last: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn get_items(&self, store: Store) -> Vec<Item> {
|
|
|
|
let items = store.get_items().await;
|
|
|
|
if let Some(item) = items.last() {
|
|
|
|
store.adjust_lseq(item.seq).await;
|
|
|
|
}
|
|
|
|
items
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn validate_token(&self, token: Token) -> bool {
|
|
|
|
token == self.token
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn id(&self) -> &Id {
|
|
|
|
&self.id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
|
|
|
|
pub struct Id {
|
|
|
|
#[serde(rename = "id")]
|
|
|
|
inner: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Id {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut data = ALPHABET.to_string().into_bytes();
|
2024-03-08 19:49:40 +01:00
|
|
|
data.repeat(ID_LEN);
|
2024-03-08 17:03:49 +01:00
|
|
|
data.shuffle(&mut rng);
|
|
|
|
Self {
|
2024-03-08 19:49:40 +01:00
|
|
|
inner: String::from_utf8(data[..ID_LEN].into()).unwrap(),
|
2024-03-08 17:03:49 +01:00
|
|
|
}
|
|
|
|
}
|
2024-03-08 19:49:40 +01:00
|
|
|
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
self.inner.len()
|
|
|
|
}
|
2024-03-08 17:03:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FromStr for Id {
|
|
|
|
type Err = Infallible;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
2024-03-08 19:49:40 +01:00
|
|
|
let s = s.replace('"', "");
|
|
|
|
Ok(Self { inner: s })
|
2024-03-08 17:03:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for Id {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
write!(f, "{}", self.inner)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-08 19:49:40 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
2024-03-08 17:03:49 +01:00
|
|
|
pub struct Token {
|
|
|
|
#[serde(rename = "token")]
|
|
|
|
inner: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Token {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut data = ALPHABET.to_string().into_bytes();
|
2024-03-08 19:49:40 +01:00
|
|
|
data.repeat(TOK_LEN);
|
2024-03-08 17:03:49 +01:00
|
|
|
data.shuffle(&mut rng);
|
|
|
|
Self {
|
2024-03-08 19:49:40 +01:00
|
|
|
inner: String::from_utf8(data[..TOK_LEN].to_vec()).unwrap(),
|
2024-03-08 17:03:49 +01:00
|
|
|
}
|
|
|
|
}
|
2024-03-08 19:49:40 +01:00
|
|
|
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
self.inner.len()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for Token {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
write!(f, "{}", self.inner)
|
|
|
|
}
|
2024-03-08 17:03:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FromStr for Token {
|
|
|
|
type Err = Infallible;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
2024-03-08 19:49:40 +01:00
|
|
|
let s = s.replace('"', "");
|
|
|
|
Ok(Self { inner: s })
|
2024-03-08 17:03:49 +01:00
|
|
|
}
|
|
|
|
}
|