feat: make identity server store user instance/guild IDs

This commit is contained in:
sam 2024-03-04 15:59:07 +01:00
parent 42abd70184
commit fd77dd01fa
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
19 changed files with 245 additions and 29 deletions

View file

@ -18,7 +18,8 @@ pub enum Payload {
/// Hello message, sent after authentication succeeds
Hello {
heartbeat_interval: u64,
guilds: Vec<String>,
guilds: Vec<GuildInstance>,
instances: Vec<InstanceId>,
},
Identify {
token: String,
@ -34,3 +35,15 @@ pub enum Payload {
timestamp: u64,
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct InstanceId {
pub id: String,
pub domain: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct GuildInstance {
pub guild_id: String,
pub instance_id: String,
}

View file

@ -1,5 +1,6 @@
use axum::http::header::ToStrError;
use thiserror::Error;
use eyre::Result;
#[derive(Error, Debug, Copy, Clone)]
pub enum FoxError {
@ -31,6 +32,8 @@ pub enum FoxError {
ChannelNotFound,
#[error("internal server error while proxying")]
ProxyInternalServerError,
#[error("invalid RestEvent for this instance type")]
InvalidRestEvent,
}
impl From<ToStrError> for FoxError {
@ -44,3 +47,16 @@ impl From<chrono::ParseError> for FoxError {
Self::InvalidDate
}
}
pub trait ToFoxError<T> {
fn to_fox_error(self) -> Result<T>;
}
impl<T> ToFoxError<T> for Option<T> {
fn to_fox_error(self) -> Result<T> {
match self {
Some(t) => Ok(t),
None => Err(FoxError::ResponseNotOk.into())
}
}
}

View file

@ -34,7 +34,7 @@ pub async fn get<R: DeserializeOwned>(
host: &str,
path: &str,
user_id: Option<String>,
) -> Result<R> {
) -> Result<Option<R>> {
let (signature, date) = build_signature(private_key, host, path, None, user_id.clone());
let mut req = CLIENT
@ -60,7 +60,7 @@ pub async fn post<T: Serialize, R: DeserializeOwned>(
path: &str,
user_id: Option<String>,
body: &T,
) -> Result<R> {
) -> Result<Option<R>> {
let body = serde_json::to_string(body)?;
let (signature, date) =
@ -85,7 +85,11 @@ pub async fn post<T: Serialize, R: DeserializeOwned>(
handle_response(resp).await.wrap_err("handling response")
}
async fn handle_response<R: DeserializeOwned>(resp: Response) -> Result<R, ResponseError> {
async fn handle_response<R: DeserializeOwned>(resp: Response) -> Result<Option<R>, ResponseError> {
if resp.status() == StatusCode::NO_CONTENT {
return Ok(None);
}
if resp.status() != StatusCode::OK {
let status = resp.status().as_u16();
@ -105,7 +109,7 @@ async fn handle_response<R: DeserializeOwned>(resp: Response) -> Result<R, Respo
.json::<R>()
.await
.map_err(|_| ResponseError::JsonError)?;
Ok(parsed)
Ok(Some(parsed))
}
#[derive(thiserror::Error, Debug, Clone)]

View file

@ -45,8 +45,6 @@ fn plaintext_string(
raw_time, host, request_path, raw_content_length, raw_user_id
);
println!("{}", s);
s
}

View file

@ -44,6 +44,7 @@ pub enum ErrorCode {
MissingSignature,
GuildNotFound,
Unauthorized,
InvalidRestEvent,
}
impl From<sqlx::Error> for ApiError {
@ -152,7 +153,12 @@ impl From<FoxError> for ApiError {
status: StatusCode::INTERNAL_SERVER_ERROR,
code: ErrorCode::InternalServerError,
message: "Internal server error".into(),
}
},
FoxError::InvalidRestEvent => ApiError {
status: StatusCode::BAD_REQUEST,
code: ErrorCode::InvalidRestEvent,
message: "Invalid RestEvent for this instance type".into(),
},
}
}
}

View file

@ -1,3 +1,5 @@
mod hello;
mod rest_event;
pub use hello::{HelloRequest, HelloResponse, NodeResponse};
pub use rest_event::RestEvent;

View file

@ -0,0 +1,18 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "t", content = "d", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum RestEvent {
/// Sent when a user creates or joins a guild (chat -> identity)
GuildJoin { guild_id: String, user_id: String },
/// Sent when a user leaves or is removed from a guild (chat -> identity)
GuildLeave { guild_id: String, user_id: String },
/// Sent when a user updates their profile (identity -> chat)
UserUpdate {
user_id: String,
username: Option<String>,
avatar: Option<String>,
},
/// Sent when a user deletes their account (identity -> chat)
UserDelete { user_id: String },
}