mirror of
https://github.com/stoatchat/stoatchat.git
synced 2026-07-14 21:47:02 +00:00
feat: initial oauth2 token revoking
This commit is contained in:
5
crates/core/database/src/models/authorized_bots/mod.rs
Normal file
5
crates/core/database/src/models/authorized_bots/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
mod model;
|
||||
mod ops;
|
||||
|
||||
pub use model::*;
|
||||
pub use ops::*;
|
||||
27
crates/core/database/src/models/authorized_bots/model.rs
Normal file
27
crates/core/database/src/models/authorized_bots/model.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use iso8601_timestamp::Timestamp;
|
||||
|
||||
auto_derived! (
|
||||
/// Unique id of the user and bot
|
||||
pub struct AuthorizedBotId {
|
||||
/// User id
|
||||
pub user: String,
|
||||
|
||||
/// Bot Id
|
||||
pub bot: String,
|
||||
}
|
||||
|
||||
pub struct AuthorizedBot {
|
||||
/// Unique Id
|
||||
#[serde(rename = "_id")]
|
||||
pub id: AuthorizedBotId,
|
||||
|
||||
/// When the authorized oauth2 bot connection was created at
|
||||
pub created_at: Timestamp,
|
||||
|
||||
/// If and when the authorized oauth2 bot connection was revoked at
|
||||
pub deauthorized_at: Option<Timestamp>,
|
||||
|
||||
/// Scopes the bot has access to
|
||||
pub scope: String
|
||||
}
|
||||
);
|
||||
27
crates/core/database/src/models/authorized_bots/ops.rs
Normal file
27
crates/core/database/src/models/authorized_bots/ops.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use revolt_result::Result;
|
||||
|
||||
use crate::{AuthorizedBot, AuthorizedBotId};
|
||||
|
||||
mod mongodb;
|
||||
mod reference;
|
||||
|
||||
#[async_trait]
|
||||
pub trait AbstractAuthorizedBots: Sync + Send {
|
||||
/// Insert emoji into database.
|
||||
async fn insert_authorized_bot(&self, authorised_bot: &AuthorizedBot) -> Result<()>;
|
||||
|
||||
/// Fetch an emoji by its id
|
||||
async fn fetch_authorized_bot(&self, id: &AuthorizedBotId) -> Result<AuthorizedBot>;
|
||||
|
||||
/// Fetch all authorized bots for a user
|
||||
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
|
||||
async fn deauthorize_authorized_bot(&self, id: &AuthorizedBotId) -> Result<AuthorizedBot>;
|
||||
|
||||
/// Fetches all deauthorized bots
|
||||
async fn fetch_deauthorized_authorized_bots(&self) -> Result<Vec<AuthorizedBot>>;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
use bson::{Document, to_bson};
|
||||
use revolt_result::Result;
|
||||
use iso8601_timestamp::Timestamp;
|
||||
|
||||
use crate::{MongoDb, AuthorizedBot, AuthorizedBotId};
|
||||
|
||||
use super::AbstractAuthorizedBots;
|
||||
|
||||
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(|_| ())
|
||||
}
|
||||
|
||||
/// Fetch an emoji 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
|
||||
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
|
||||
async fn delete_authorized_bot(&self, id: &AuthorizedBotId) -> Result<()> {
|
||||
query!(self, delete_one, COL, doc! { "id.user": &id.user, "id.bot": &id.bot }).map(|_| ())
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
)
|
||||
.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)))
|
||||
}
|
||||
|
||||
async fn fetch_deauthorized_authorized_bots(&self) -> Result<Vec<AuthorizedBot>> {
|
||||
query!(
|
||||
self,
|
||||
find,
|
||||
COL,
|
||||
doc! {
|
||||
"deauthorized_at": { "$exists": true }
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
use bson::Document;
|
||||
use revolt_result::Result;
|
||||
|
||||
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!()
|
||||
}
|
||||
|
||||
/// Fetch an emoji by its id
|
||||
async fn fetch_authorized_bot(&self, id: &AuthorizedBotId) -> Result<AuthorizedBot> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn fetch_users_authorized_bots(&self, user_id: &str) -> Result<Vec<AuthorizedBot>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Deletes an authori
|
||||
async fn delete_authorized_bot(&self, id: &AuthorizedBotId) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn deauthorize_authorized_bot(&self, id: &AuthorizedBotId) -> Result<AuthorizedBot> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn fetch_deauthorized_authorized_bots(&self) -> Result<Vec<AuthorizedBot>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
mod admin_migrations;
|
||||
mod authorized_bots;
|
||||
mod bots;
|
||||
mod channel_invites;
|
||||
mod channel_unreads;
|
||||
@@ -19,6 +20,7 @@ mod user_settings;
|
||||
mod users;
|
||||
|
||||
pub use admin_migrations::*;
|
||||
pub use authorized_bots::*;
|
||||
pub use bots::*;
|
||||
pub use channel_invites::*;
|
||||
pub use channel_unreads::*;
|
||||
@@ -46,6 +48,7 @@ use crate::MongoDb;
|
||||
pub trait AbstractDatabase:
|
||||
Sync
|
||||
+ Send
|
||||
+ authorized_bots::AbstractAuthorizedBots
|
||||
+ admin_migrations::AbstractMigrations
|
||||
+ bots::AbstractBots
|
||||
+ channels::AbstractChannels
|
||||
|
||||
@@ -1454,3 +1454,43 @@ impl From<FieldsMessage> for crate::FieldsMessage {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AuthorizedBotId> for crate::AuthorizedBotId {
|
||||
fn from(value: AuthorizedBotId) -> Self {
|
||||
crate::AuthorizedBotId {
|
||||
user: value.user,
|
||||
bot: value.bot
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::AuthorizedBotId> for AuthorizedBotId {
|
||||
fn from(value: crate::AuthorizedBotId) -> Self {
|
||||
AuthorizedBotId {
|
||||
user: value.user,
|
||||
bot: value.bot
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AuthorizedBot> for crate::AuthorizedBot {
|
||||
fn from(value: AuthorizedBot) -> Self {
|
||||
crate::AuthorizedBot {
|
||||
id: value.id.into(),
|
||||
created_at: value.created_at,
|
||||
deauthorized_at: value.deauthorized_at,
|
||||
scope: value.scope
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::AuthorizedBot> for AuthorizedBot {
|
||||
fn from(value: crate::AuthorizedBot) -> Self {
|
||||
AuthorizedBot {
|
||||
id: value.id.into(),
|
||||
created_at: value.created_at,
|
||||
deauthorized_at: value.deauthorized_at,
|
||||
scope: value.scope
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user