feat: initial work on refresh tokens

This commit is contained in:
Zomatree
2025-07-05 00:58:57 +01:00
parent 660e646b2b
commit ef65223c89
15 changed files with 210 additions and 79 deletions

View File

@@ -5,13 +5,14 @@ use futures::lock::Mutex;
use crate::{
Bot, Channel, ChannelCompositeKey, ChannelUnread, Emoji, File, FileHash, Invite, Member,
MemberCompositeKey, Message, PolicyChange, RatelimitEvent, Report, Server, ServerBan, Snapshot,
User, UserSettings, Webhook,
User, UserSettings, Webhook, AuthorizedBotId, AuthorizedBot,
};
database_derived!(
/// Reference implementation
#[derive(Default)]
pub struct ReferenceDb {
pub authorized_bots: Arc<Mutex<HashMap<AuthorizedBotId, AuthorizedBot>>>,
pub bots: Arc<Mutex<HashMap<String, Bot>>>,
pub channels: Arc<Mutex<HashMap<String, Channel>>>,
pub channel_invites: Arc<Mutex<HashMap<String, Invite>>>,

View File

@@ -2,6 +2,7 @@ use iso8601_timestamp::Timestamp;
auto_derived! (
/// Unique id of the user and bot
#[derive(Hash)]
pub struct AuthorizedBotId {
/// User id
pub user: String,

View File

@@ -8,20 +8,20 @@ mod reference;
#[async_trait]
pub trait AbstractAuthorizedBots: Sync + Send {
/// Insert emoji into database.
async fn insert_authorized_bot(&self, authorised_bot: &AuthorizedBot) -> Result<()>;
async fn insert_authorized_bot(&self, authorized_bot: &AuthorizedBot) -> Result<()>;
/// Fetch an emoji by its id
/// Fetch an authorized bot by its id
async fn fetch_authorized_bot(&self, id: &AuthorizedBotId) -> Result<AuthorizedBot>;
/// Fetch all authorized bots for a user
/// Fetch a users authorized bot by its id
async fn fetch_users_authorized_bots(&self, user_id: &str) -> Result<Vec<AuthorizedBot>>;
/// Deletes an authorized bot
async fn delete_authorized_bot(&self, id: &AuthorizedBotId) -> Result<()>;
/// Deauthorizes a bot access to a user's information
/// Deauthorizes an authorized bot
async fn deauthorize_authorized_bot(&self, id: &AuthorizedBotId) -> Result<AuthorizedBot>;
/// Fetches all deauthorized bots
// Fetches all authorized bots which have been deauthorized
async fn fetch_deauthorized_authorized_bots(&self) -> Result<Vec<AuthorizedBot>>;
}

View File

@@ -1,4 +1,4 @@
use bson::{Document, to_bson};
use bson::to_bson;
use revolt_result::Result;
use iso8601_timestamp::Timestamp;
@@ -10,44 +10,46 @@ static COL: &str = "authorized_bots";
#[async_trait]
impl AbstractAuthorizedBots for MongoDb {
/// Insert emoji into database.
async fn insert_authorized_bot(&self, authorised_bot: &AuthorizedBot) -> Result<()> {
query!(self, insert_one, COL, &authorised_bot).map(|_| ())
/// Insert an authorized bot into database.
async fn insert_authorized_bot(&self, authorized_bot: &AuthorizedBot) -> Result<()> {
query!(self, insert_one, COL, &authorized_bot).map(|_| ())
}
/// Fetch an emoji by its id
/// Fetch an authorized bot by its id
async fn fetch_authorized_bot(&self, id: &AuthorizedBotId) -> Result<AuthorizedBot> {
query!(self, find_one, COL, doc! { "id.user": &id.user, "id.bot": &id.bot })?.ok_or_else(|| create_error!(NotFound))
}
/// Fetch an emoji by its id
/// Fetch a users authorized bot by its id
async fn fetch_users_authorized_bots(&self, user_id: &str) -> Result<Vec<AuthorizedBot>> {
query!(self, find, COL, doc! { "id.user": &user_id })
}
/// Deletes an authori
/// Deletes an authorized bot
async fn delete_authorized_bot(&self, id: &AuthorizedBotId) -> Result<()> {
query!(self, delete_one, COL, doc! { "id.user": &id.user, "id.bot": &id.bot }).map(|_| ())
}
/// Deauthorizes an authorized bot
async fn deauthorize_authorized_bot(&self, id: &AuthorizedBotId) -> Result<AuthorizedBot> {
self.col::<AuthorizedBot>(COL)
.find_one_and_update(
doc! {
"id.user": &id.user,
"id.bot": &id.bot
},
doc! {
"$set": {
"unauthorized_at": to_bson(&Timestamp::now_utc()).unwrap()
doc! {
"id.user": &id.user,
"id.bot": &id.bot
},
doc! {
"$set": {
"deauthorized_at": to_bson(&Timestamp::now_utc()).unwrap()
}
}
}
)
.await
.map_err(|_| create_database_error!("find_one_and_update", COL))
.and_then(|opt| opt.ok_or_else(|| create_database_error!("find_one_and_update", COL)))
}
// Fetches all authorized bots which have been deauthorized
async fn fetch_deauthorized_authorized_bots(&self) -> Result<Vec<AuthorizedBot>> {
query!(
self,

View File

@@ -1,38 +1,76 @@
use bson::Document;
use revolt_result::Result;
use iso8601_timestamp::Timestamp;
use crate::{ReferenceDb, AuthorizedBot, AuthorizedBotId};
use super::AbstractAuthorizedBots;
static COL: &str = "authorized_bots";
#[async_trait]
impl AbstractAuthorizedBots for ReferenceDb {
/// Insert emoji into database.
async fn insert_authorized_bot(&self, authorised_bot: &AuthorizedBot) -> Result<()> {
todo!()
/// Insert an authorized bot into database.
async fn insert_authorized_bot(&self, authorized_bot: &AuthorizedBot) -> Result<()> {
let mut authorized_bots = self.authorized_bots.lock().await;
if authorized_bots.contains_key(&authorized_bot.id) {
Err(create_database_error!("insert", "authorized_bots"))
} else {
authorized_bots.insert(authorized_bot.id.clone(), authorized_bot.clone());
Ok(())
}
}
/// Fetch an emoji by its id
/// Fetch an authorized bot by its id
async fn fetch_authorized_bot(&self, id: &AuthorizedBotId) -> Result<AuthorizedBot> {
todo!()
let authorized_bots = self.authorized_bots.lock().await;
authorized_bots.get(id).cloned().ok_or_else(|| create_error!(NotFound))
}
/// Fetch a users authorized bot by its id
async fn fetch_users_authorized_bots(&self, user_id: &str) -> Result<Vec<AuthorizedBot>> {
todo!()
let authorized_bots = self.authorized_bots.lock().await;
Ok(authorized_bots
.values()
.filter(|authorized_bot| authorized_bot.id.user == user_id)
.cloned()
.collect()
)
}
/// Deletes an authori
/// Deletes an authorized bot
async fn delete_authorized_bot(&self, id: &AuthorizedBotId) -> Result<()> {
todo!()
let mut authorized_bots = self.authorized_bots.lock().await;
if authorized_bots.remove(id).is_some() {
Ok(())
} else {
Err(create_error!(NotFound))
}
}
/// Deauthorizes an authorized bot
async fn deauthorize_authorized_bot(&self, id: &AuthorizedBotId) -> Result<AuthorizedBot> {
todo!()
let mut authorized_bots = self.authorized_bots.lock().await;
if let Some(authorized_bot) = authorized_bots.get_mut(id) {
authorized_bot.deauthorized_at = Some(Timestamp::now_utc());
Ok(authorized_bot.clone())
} else {
Err(create_error!(NotFound))
}
}
// Fetches all authorized bots which have been deauthorized
async fn fetch_deauthorized_authorized_bots(&self) -> Result<Vec<AuthorizedBot>> {
todo!()
let authorized_bots = self.authorized_bots.lock().await;
Ok(authorized_bots
.values()
.filter(|authorized_bot| authorized_bot.deauthorized_at.is_some())
.cloned()
.collect()
)
}
}