feat: allow connecting to ws via oauth2
This commit is contained in:
@@ -33,7 +33,7 @@ pub async fn auth(
|
||||
return Err(create_error!(InvalidOperation));
|
||||
};
|
||||
|
||||
if scopes.into_iter().any(|scope| !oauth2.allowed_scopes.contains_key(&scope.into()))
|
||||
if scopes.iter().any(|&scope| !oauth2.allowed_scopes.contains_key(&scope.into()))
|
||||
|| !oauth2.redirects.contains(&info.redirect_uri)
|
||||
|| v0::OAuth2Scope::scopes_from_str(&info.scope).is_none()
|
||||
{
|
||||
@@ -55,7 +55,7 @@ pub async fn auth(
|
||||
user.id.clone(),
|
||||
info.client_id.clone(),
|
||||
info.redirect_uri.clone(),
|
||||
info.scope.clone(),
|
||||
scopes.clone(),
|
||||
info.code_challenge_method,
|
||||
)
|
||||
.map_err(|_| create_error!(InternalError))?;
|
||||
@@ -64,7 +64,7 @@ pub async fn auth(
|
||||
id: AuthorizedBotId { bot: info.client_id.clone(), user: user.id.clone() },
|
||||
created_at: Timestamp::now_utc(),
|
||||
deauthorized_at: None,
|
||||
scope: info.scope.clone()
|
||||
scope: scopes.iter().map(|&scope| scope.into()).collect()
|
||||
}).await?;
|
||||
|
||||
token
|
||||
@@ -87,11 +87,11 @@ pub async fn auth(
|
||||
|
||||
let token = oauth2::encode_token(
|
||||
&config.api.security.token_secret,
|
||||
oauth2::TokenType::Access,
|
||||
oauth2::TokenType::Auth,
|
||||
user.id.clone(),
|
||||
info.client_id.clone(),
|
||||
info.redirect_uri.clone(),
|
||||
info.scope.clone(),
|
||||
scopes.clone(),
|
||||
info.code_challenge_method,
|
||||
)
|
||||
.map_err(|_| create_error!(InternalError))?;
|
||||
|
||||
@@ -45,10 +45,10 @@ pub async fn token(
|
||||
return Err(create_error!(NotAuthenticated))
|
||||
};
|
||||
|
||||
let authorized_bot = db.fetch_authorized_bot(&AuthorizedBotId { user: claims.sub.clone(), bot: claims.client_id.clone() }).await?;
|
||||
|
||||
if authorized_bot.deauthorized_at.is_some() {
|
||||
return Err(create_error!(NotAuthenticated));
|
||||
if let Ok(authorized_bot) = db.fetch_authorized_bot(&AuthorizedBotId { user: claims.sub.clone(), bot: claims.client_id.clone() }).await {
|
||||
if authorized_bot.deauthorized_at.is_some() {
|
||||
return Err(create_error!(NotAuthenticated));
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: track used tokens and dont allow them to be used twice
|
||||
@@ -88,7 +88,7 @@ pub async fn token(
|
||||
claims.sub.clone(),
|
||||
claims.client_id.clone(),
|
||||
claims.redirect_uri.clone(),
|
||||
claims.scope.clone(),
|
||||
claims.scopes.clone(),
|
||||
None,
|
||||
)
|
||||
.map_err(|_| create_error!(InternalError))?;
|
||||
@@ -99,19 +99,23 @@ pub async fn token(
|
||||
claims.sub.clone(),
|
||||
claims.client_id.clone(),
|
||||
claims.redirect_uri.clone(),
|
||||
claims.scope.clone(),
|
||||
claims.scopes.clone(),
|
||||
None,
|
||||
)
|
||||
.map_err(|_| create_error!(InternalError))?;
|
||||
|
||||
let authorized_bot_id = AuthorizedBotId { bot: claims.client_id.clone(), user: claims.sub.clone() };
|
||||
let auth_bot = db.fetch_authorized_bot(&authorized_bot_id).await;
|
||||
println!("{auth_bot:?}");
|
||||
|
||||
if auth_bot.is_err_and(|err| err.error_type == ErrorType::NotFound) {
|
||||
println!("inserting");
|
||||
|
||||
if db.fetch_authorized_bot(&authorized_bot_id).await.is_err_and(|err| err.error_type == ErrorType::NotFound) {
|
||||
db.insert_authorized_bot(&AuthorizedBot {
|
||||
id: authorized_bot_id,
|
||||
created_at: Timestamp::now_utc(),
|
||||
deauthorized_at: None,
|
||||
scope: claims.scope.clone()
|
||||
scope: claims.scopes.iter().map(|&scope| scope.into()).collect()
|
||||
}).await?;
|
||||
}
|
||||
|
||||
@@ -119,7 +123,7 @@ pub async fn token(
|
||||
access_token: token,
|
||||
refresh_token: Some(refresh_token),
|
||||
token_type: "OAuth2".to_string(),
|
||||
scope: claims.scope,
|
||||
scope: claims.scopes.iter().map(|scope| scope.to_string()).collect::<Vec<_>>().join(" "),
|
||||
}))
|
||||
},
|
||||
v0::OAuth2GrantType::RefreshToken => {
|
||||
@@ -133,7 +137,7 @@ pub async fn token(
|
||||
claims.sub.clone(),
|
||||
claims.client_id.clone(),
|
||||
claims.redirect_uri.clone(),
|
||||
claims.scope.clone(),
|
||||
claims.scopes.clone(),
|
||||
None,
|
||||
)
|
||||
.map_err(|_| create_error!(InternalError))?;
|
||||
@@ -144,7 +148,7 @@ pub async fn token(
|
||||
claims.sub.clone(),
|
||||
claims.client_id.clone(),
|
||||
claims.redirect_uri.clone(),
|
||||
claims.scope.clone(),
|
||||
claims.scopes.clone(),
|
||||
None,
|
||||
)
|
||||
.map_err(|_| create_error!(InternalError))?;
|
||||
@@ -153,7 +157,7 @@ pub async fn token(
|
||||
access_token: token,
|
||||
refresh_token: Some(refresh_token),
|
||||
token_type: "OAuth2".to_string(),
|
||||
scope: claims.scope,
|
||||
scope: claims.scopes.iter().map(|scope| scope.to_string()).collect::<Vec<_>>().join(" "),
|
||||
}))
|
||||
}
|
||||
v0::OAuth2GrantType::Implicit => {
|
||||
|
||||
@@ -29,7 +29,7 @@ pub fn routes() -> (Vec<Route>, OpenApi) {
|
||||
openapi_get_routes_spec![
|
||||
server_create::create_server,
|
||||
server_delete::delete,
|
||||
server_fetch::fetch,
|
||||
server_fetch::fetch_server,
|
||||
server_edit::edit,
|
||||
server_ack::ack,
|
||||
channel_create::create_server_channel,
|
||||
|
||||
@@ -12,7 +12,7 @@ use rocket::{serde::json::Json, State};
|
||||
/// Fetch a server by its id.
|
||||
#[openapi(tag = "Server Information")]
|
||||
#[get("/<target>?<options..>")]
|
||||
pub async fn fetch(
|
||||
pub async fn fetch_server(
|
||||
db: &State<Database>,
|
||||
user: User,
|
||||
target: Reference<'_>,
|
||||
|
||||
@@ -8,6 +8,6 @@ use rocket::serde::json::Json;
|
||||
/// Retrieve your user information.
|
||||
#[openapi(tag = "User Information")]
|
||||
#[get("/@me")]
|
||||
pub async fn fetch(user: User) -> Result<Json<v0::User>> {
|
||||
pub async fn fetch_self(user: User) -> Result<Json<v0::User>> {
|
||||
Ok(Json(user.into_self(false).await))
|
||||
}
|
||||
|
||||
53
crates/delta/src/routes/users/fetch_self_servers.rs
Normal file
53
crates/delta/src/routes/users/fetch_self_servers.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
use revolt_database::{util::permissions::DatabasePermissionQuery, Database, User};
|
||||
use revolt_models::v0;
|
||||
use revolt_permissions::{calculate_channel_permissions, ChannelPermission};
|
||||
use revolt_result::Result;
|
||||
use rocket::{serde::json::Json, State};
|
||||
|
||||
/// # Fetch current user's servers
|
||||
///
|
||||
/// Retrieve all servers the current user is in.
|
||||
#[openapi(tag = "User Information")]
|
||||
#[get("/@me/servers?<options..>")]
|
||||
pub async fn fetch_self_servers(
|
||||
db: &State<Database>,
|
||||
user: User,
|
||||
options: v0::OptionsFetchServer,
|
||||
) -> Result<Json<Vec<v0::FetchServerResponse>>> {
|
||||
let members = db.fetch_all_memberships(&user.id).await?;
|
||||
|
||||
let server_ids = members
|
||||
.iter()
|
||||
.map(|x| x.id.server.clone())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut servers: Vec<v0::FetchServerResponse> = Vec::new();
|
||||
|
||||
for server in db.fetch_servers(&server_ids).await? {
|
||||
if let Some(true) = options.include_channels {
|
||||
let query = DatabasePermissionQuery::new(db, &user).server(&server);
|
||||
|
||||
let all_channels = db.fetch_channels(&server.channels).await?;
|
||||
let mut visible_channels: Vec<v0::Channel> = vec![];
|
||||
|
||||
for channel in all_channels {
|
||||
let mut channel_query = query.clone().channel(&channel);
|
||||
if calculate_channel_permissions(&mut channel_query)
|
||||
.await
|
||||
.has_channel_permission(ChannelPermission::ViewChannel)
|
||||
{
|
||||
visible_channels.push(channel.into());
|
||||
}
|
||||
}
|
||||
|
||||
servers.push(v0::FetchServerResponse::ServerWithChannels {
|
||||
server: server.into(),
|
||||
channels: visible_channels,
|
||||
});
|
||||
} else {
|
||||
servers.push(v0::FetchServerResponse::JustServer(server.into()))
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Json(servers))
|
||||
}
|
||||
@@ -7,6 +7,7 @@ mod change_username;
|
||||
mod edit_user;
|
||||
mod fetch_dms;
|
||||
mod fetch_profile;
|
||||
mod fetch_self_servers;
|
||||
mod fetch_self;
|
||||
mod fetch_user;
|
||||
mod fetch_user_flags;
|
||||
@@ -20,7 +21,8 @@ mod unblock_user;
|
||||
pub fn routes() -> (Vec<Route>, OpenApi) {
|
||||
openapi_get_routes_spec![
|
||||
// User Information
|
||||
fetch_self::fetch,
|
||||
fetch_self::fetch_self,
|
||||
fetch_self_servers::fetch_self_servers,
|
||||
fetch_user::fetch,
|
||||
fetch_user_flags::fetch_user_flags,
|
||||
edit_user::edit,
|
||||
|
||||
Reference in New Issue
Block a user