You've already forked AstralRinth
forked from didirus/AstralRinth
* Fix not being able to connect to local friends socket * Start basic work on tunneling protocol and move some code into a common crate * Commonize message serialization logic * Serialize Base62Ids as u64 when human-readability is not required * Move ActiveSockets tuple into struct * Make CI run when rust-common is updated CI is currently broken for labrinth, however * Fix theseus-release.yml to reference itself correctly * Implement Labrinth side of tunneling * Implement non-friend part of theseus tunneling * Implement client-side except for socket loop * Implement the socket loop Doesn't work though. Debugging time! * Fix config.rs * Fix deadlock in labrinth socket handling * Update dockerfile * switch to workspace prepare at root level * Wait for connection before tunneling in playground * Move rust-common into labrinth * Remove rust-common references from Actions * Revert "Update dockerfile" This reverts commit 3caad59bb474ce425d0b8928d7cee7ae1a5011bd. * Fix Docker build * Rebuild Theseus if common code changes * Allow multiple connections from the same user * Fix test building * Move FriendSocketListening and FriendSocketStoppedListening to non-panicking TODO for now * Make message_serialization macro take varargs for binary messages * Improve syntax of message_serialization macro * Remove the ability to connect to a virtual socket, and disable the ability to listen on one * Allow the app to compile without running labrinth * Clippy fix * Update Rust and Clippy fix again --------- Co-authored-by: Jai A <jaiagr+gpg@pm.me>
219 lines
7.3 KiB
Rust
219 lines
7.3 KiB
Rust
use super::ids::Base62Id;
|
|
use super::ids::OrganizationId;
|
|
use super::users::UserId;
|
|
use crate::database::models::notification_item::Notification as DBNotification;
|
|
use crate::database::models::notification_item::NotificationAction as DBNotificationAction;
|
|
use crate::models::ids::{
|
|
ProjectId, ReportId, TeamId, ThreadId, ThreadMessageId, VersionId,
|
|
};
|
|
use crate::models::projects::ProjectStatus;
|
|
use chrono::{DateTime, Utc};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
#[serde(from = "Base62Id")]
|
|
#[serde(into = "Base62Id")]
|
|
pub struct NotificationId(pub u64);
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
pub struct Notification {
|
|
pub id: NotificationId,
|
|
pub user_id: UserId,
|
|
pub read: bool,
|
|
pub created: DateTime<Utc>,
|
|
pub body: NotificationBody,
|
|
|
|
pub name: String,
|
|
pub text: String,
|
|
pub link: String,
|
|
pub actions: Vec<NotificationAction>,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Clone)]
|
|
#[serde(tag = "type", rename_all = "snake_case")]
|
|
pub enum NotificationBody {
|
|
ProjectUpdate {
|
|
project_id: ProjectId,
|
|
version_id: VersionId,
|
|
},
|
|
TeamInvite {
|
|
project_id: ProjectId,
|
|
team_id: TeamId,
|
|
invited_by: UserId,
|
|
role: String,
|
|
},
|
|
OrganizationInvite {
|
|
organization_id: OrganizationId,
|
|
invited_by: UserId,
|
|
team_id: TeamId,
|
|
role: String,
|
|
},
|
|
StatusChange {
|
|
project_id: ProjectId,
|
|
old_status: ProjectStatus,
|
|
new_status: ProjectStatus,
|
|
},
|
|
ModeratorMessage {
|
|
thread_id: ThreadId,
|
|
message_id: ThreadMessageId,
|
|
|
|
project_id: Option<ProjectId>,
|
|
report_id: Option<ReportId>,
|
|
},
|
|
LegacyMarkdown {
|
|
notification_type: Option<String>,
|
|
name: String,
|
|
text: String,
|
|
link: String,
|
|
actions: Vec<NotificationAction>,
|
|
},
|
|
Unknown,
|
|
}
|
|
|
|
impl From<DBNotification> for Notification {
|
|
fn from(notif: DBNotification) -> Self {
|
|
let (name, text, link, actions) = {
|
|
match ¬if.body {
|
|
NotificationBody::ProjectUpdate {
|
|
project_id,
|
|
version_id,
|
|
} => (
|
|
"A project you follow has been updated!".to_string(),
|
|
format!(
|
|
"The project {} has released a new version: {}",
|
|
project_id, version_id
|
|
),
|
|
format!("/project/{}/version/{}", project_id, version_id),
|
|
vec![],
|
|
),
|
|
NotificationBody::TeamInvite {
|
|
project_id,
|
|
role,
|
|
team_id,
|
|
..
|
|
} => (
|
|
"You have been invited to join a team!".to_string(),
|
|
format!("An invite has been sent for you to be {} of a team", role),
|
|
format!("/project/{}", project_id),
|
|
vec![
|
|
NotificationAction {
|
|
name: "Accept".to_string(),
|
|
action_route: ("POST".to_string(), format!("team/{team_id}/join")),
|
|
},
|
|
NotificationAction {
|
|
name: "Deny".to_string(),
|
|
action_route: (
|
|
"DELETE".to_string(),
|
|
format!("team/{team_id}/members/{}", UserId::from(notif.user_id)),
|
|
),
|
|
},
|
|
],
|
|
),
|
|
NotificationBody::OrganizationInvite {
|
|
organization_id,
|
|
role,
|
|
team_id,
|
|
..
|
|
} => (
|
|
"You have been invited to join an organization!".to_string(),
|
|
format!(
|
|
"An invite has been sent for you to be {} of an organization",
|
|
role
|
|
),
|
|
format!("/organization/{}", organization_id),
|
|
vec![
|
|
NotificationAction {
|
|
name: "Accept".to_string(),
|
|
action_route: ("POST".to_string(), format!("team/{team_id}/join")),
|
|
},
|
|
NotificationAction {
|
|
name: "Deny".to_string(),
|
|
action_route: (
|
|
"DELETE".to_string(),
|
|
format!(
|
|
"organization/{organization_id}/members/{}",
|
|
UserId::from(notif.user_id)
|
|
),
|
|
),
|
|
},
|
|
],
|
|
),
|
|
NotificationBody::StatusChange {
|
|
old_status,
|
|
new_status,
|
|
project_id,
|
|
} => (
|
|
"Project status has changed".to_string(),
|
|
format!(
|
|
"Status has changed from {} to {}",
|
|
old_status.as_friendly_str(),
|
|
new_status.as_friendly_str()
|
|
),
|
|
format!("/project/{}", project_id),
|
|
vec![],
|
|
),
|
|
NotificationBody::ModeratorMessage {
|
|
project_id,
|
|
report_id,
|
|
..
|
|
} => (
|
|
"A moderator has sent you a message!".to_string(),
|
|
"Click on the link to read more.".to_string(),
|
|
if let Some(project_id) = project_id {
|
|
format!("/project/{}", project_id)
|
|
} else if let Some(report_id) = report_id {
|
|
format!("/project/{}", report_id)
|
|
} else {
|
|
"#".to_string()
|
|
},
|
|
vec![],
|
|
),
|
|
NotificationBody::LegacyMarkdown {
|
|
name,
|
|
text,
|
|
link,
|
|
actions,
|
|
..
|
|
} => (
|
|
name.clone(),
|
|
text.clone(),
|
|
link.clone(),
|
|
actions.clone().into_iter().collect(),
|
|
),
|
|
NotificationBody::Unknown => {
|
|
("".to_string(), "".to_string(), "#".to_string(), vec![])
|
|
}
|
|
}
|
|
};
|
|
|
|
Self {
|
|
id: notif.id.into(),
|
|
user_id: notif.user_id.into(),
|
|
body: notif.body,
|
|
read: notif.read,
|
|
created: notif.created,
|
|
|
|
name,
|
|
text,
|
|
link,
|
|
actions,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Clone)]
|
|
pub struct NotificationAction {
|
|
pub name: String,
|
|
/// The route to call when this notification action is called. Formatted HTTP Method, route
|
|
pub action_route: (String, String),
|
|
}
|
|
|
|
impl From<DBNotificationAction> for NotificationAction {
|
|
fn from(act: DBNotificationAction) -> Self {
|
|
Self {
|
|
name: act.name,
|
|
action_route: (act.action_route_method, act.action_route),
|
|
}
|
|
}
|
|
}
|