mirror of
https://github.com/stoatchat/stoatchat.git
synced 2026-07-14 21:47:02 +00:00
feat: allowed scopes
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use revolt_result::Result;
|
||||
use ulid::Ulid;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{events::client::EventV1, BotInformation, Database, PartialUser, User};
|
||||
|
||||
@@ -46,6 +47,19 @@ auto_derived_partial!(
|
||||
"PartialBot"
|
||||
);
|
||||
|
||||
auto_derived!(
|
||||
#[derive(Copy, Hash)]
|
||||
pub enum OAuth2Scope {
|
||||
Identify,
|
||||
Full,
|
||||
}
|
||||
|
||||
pub struct OAuth2ScopeReasoning {
|
||||
pub allow: String,
|
||||
pub deny: String
|
||||
}
|
||||
);
|
||||
|
||||
auto_derived_partial!(
|
||||
pub struct BotOauth2 {
|
||||
/// Whether the oauth2 client is public and should not receive a secret key
|
||||
@@ -56,7 +70,10 @@ auto_derived_partial!(
|
||||
pub secret: Option<String>,
|
||||
/// Allowed redirects for the authorisation
|
||||
#[serde(default)]
|
||||
pub redirects: Vec<String>
|
||||
pub redirects: Vec<String>,
|
||||
/// Mapping of allowed scopes and the reasonings
|
||||
#[serde(default)]
|
||||
pub allowed_scopes: HashMap<OAuth2Scope, OAuth2ScopeReasoning>,
|
||||
},
|
||||
"PartialBotOauth2"
|
||||
);
|
||||
@@ -96,7 +113,8 @@ impl Default for BotOauth2 {
|
||||
Self {
|
||||
public: false,
|
||||
secret: Some(nanoid::nanoid!(64)),
|
||||
redirects: Default::default()
|
||||
redirects: Vec::new(),
|
||||
allowed_scopes: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,10 @@ impl From<BotOauth2> for crate::BotOauth2 {
|
||||
public: value.public,
|
||||
secret: value.secret,
|
||||
redirects: value.redirects,
|
||||
allowed_scopes: value.allowed_scopes
|
||||
.into_iter()
|
||||
.map(|(scope, value)| (scope.into(), value.into()))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,6 +81,46 @@ impl From<crate::BotOauth2> for BotOauth2 {
|
||||
public: value.public,
|
||||
secret: value.secret,
|
||||
redirects: value.redirects,
|
||||
allowed_scopes: value.allowed_scopes
|
||||
.into_iter()
|
||||
.map(|(scope, value)| (scope.into(), value.into()))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::OAuth2Scope> for OAuth2Scope {
|
||||
fn from(value: crate::OAuth2Scope) -> Self {
|
||||
match value {
|
||||
crate::OAuth2Scope::Identify => OAuth2Scope::Identify,
|
||||
crate::OAuth2Scope::Full => OAuth2Scope::Full,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OAuth2Scope> for crate::OAuth2Scope {
|
||||
fn from(value: OAuth2Scope) -> Self {
|
||||
match value {
|
||||
OAuth2Scope::Identify => crate::OAuth2Scope::Identify,
|
||||
OAuth2Scope::Full => crate::OAuth2Scope::Full,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::OAuth2ScopeReasoning> for OAuth2ScopeReasoning {
|
||||
fn from(value: crate::OAuth2ScopeReasoning) -> Self {
|
||||
OAuth2ScopeReasoning {
|
||||
allow: value.allow,
|
||||
deny: value.deny,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OAuth2ScopeReasoning> for crate::OAuth2ScopeReasoning {
|
||||
fn from(value: OAuth2ScopeReasoning) -> Self {
|
||||
crate::OAuth2ScopeReasoning {
|
||||
allow: value.allow,
|
||||
deny: value.deny,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,49 +2,12 @@ use chrono::{TimeDelta, Utc};
|
||||
use jsonwebtoken::{decode, encode, errors::Error, DecodingKey, EncodingKey, Header, Validation};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use revolt_models::v0;
|
||||
use redis_kiss::AsyncCommands;
|
||||
use revolt_result::Result;
|
||||
|
||||
#[cfg(feature = "rocket")]
|
||||
use rocket::{http::Method, Request};
|
||||
|
||||
// use redis_kiss::{get_connection, redis::Pipeline, AsyncCommands};
|
||||
// use revolt_result::Result;
|
||||
|
||||
// pub async fn add_access_token(code: &str, redirect_uri: &str, client_id: &str) -> Result<()> {
|
||||
// let conn = get_connection()
|
||||
// .await
|
||||
// .map_err(|_| create_error!(InternalError))?;
|
||||
|
||||
// // 10 mins
|
||||
// Pipeline::new()
|
||||
// .pset_ex(format!("oauth:{code}:client_id"), client_id, 600000)
|
||||
// .pset_ex(format!("oauth:{code}:redirect_uri"), redirect_uri, 600000)
|
||||
// .query_async::<_, ()>(&mut conn.into_inner())
|
||||
// .await
|
||||
// .map_err(|_| create_error!(InternalError))?;
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// pub struct CodeInfo {
|
||||
// pub redirect_uri: String,
|
||||
// pub client_id: String
|
||||
// }
|
||||
|
||||
// pub async fn get_access_token_info(code: &str) -> Result<CodeInfo> {
|
||||
// let conn = get_connection()
|
||||
// .await
|
||||
// .map_err(|_| create_error!(InternalError))?;
|
||||
|
||||
// let (redirect_uri, client_id) = Pipeline::new()
|
||||
// .get(format!("oauth:{code}:client_id"))
|
||||
// .get(format!("oauth:{code}:redirect_uri"))
|
||||
// .query_async::<_, (String, String)>(&mut conn.into_inner())
|
||||
// .await
|
||||
// .map_err(|_| create_error!(InternalError))?;
|
||||
|
||||
// Ok(CodeInfo { redirect_uri, client_id })
|
||||
// }
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum TokenType {
|
||||
Auth,
|
||||
@@ -144,4 +107,20 @@ pub fn scopes_can_access_route(scopes: &str, request: &Request<'_>) -> bool {
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub async fn add_code_challange(token: &str, code_challenge: &str) -> Result<()> {
|
||||
let mut conn = redis_kiss::get_connection()
|
||||
.await
|
||||
.map_err(|_| create_error!(InternalError))?;
|
||||
|
||||
conn.pset_ex::<_, _, ()>(
|
||||
format!("oauth2:{token}:code_challenge"),
|
||||
code_challenge,
|
||||
TokenType::Access.lifetime().num_milliseconds() as usize
|
||||
)
|
||||
.await
|
||||
.map_err(|_| create_error!(InternalError))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user