refactor(models): update data models and remove deprecated IM entities

- Update channel, notification, PR, repo, user, workspace models
- Remove deleted IM models: articles, channel follows, message
  attachments/bookmarks/drafts/edit history/embeds/mentions/pins/
  polls/reactions/threads, saved messages, thread read states
- Add new PR models: review requests, templates
- Add repo release assets model
- Add base_info module for API detail responses
This commit is contained in:
zhenyi
2026-06-10 18:49:37 +08:00
parent 420dedbc1e
commit 9eb77ab98b
50 changed files with 827 additions and 440 deletions
+330
View File
@@ -0,0 +1,330 @@
//! BaseInfo structs — stable, minimal projections of core entities for API/WS responses.
//!
//! Every raw UUID foreign key in API / WebSocket responses must be expanded
//! to its corresponding `*BaseInfo` object so frontend consumers never
//! receive bare identifiers.
//!
//! Batch resolvers are provided to avoid N+1 queries when enriching
//! collections of entities.
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::error::AppError;
use crate::models::common::{ChannelType, State, Visibility};
use crate::models::db::AppDatabase;
// Section: BaseInfo structs
#[derive(Debug, Clone, Default, Serialize, Deserialize, utoipa::ToSchema)]
pub struct UserBaseInfo {
pub id: Uuid,
pub username: String,
pub display_name: Option<String>,
pub avatar_url: Option<String>,
pub is_bot: bool,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, utoipa::ToSchema)]
pub struct WorkspaceBaseInfo {
pub id: Uuid,
pub name: String,
pub avatar_url: Option<String>,
pub visibility: Visibility,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct RepoBaseInfo {
pub id: Uuid,
pub name: String,
pub workspace_id: Uuid,
pub visibility: Visibility,
pub is_fork: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct ChannelBaseInfo {
pub id: Uuid,
pub name: String,
pub channel_type: ChannelType,
pub workspace_id: Uuid,
pub archived: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct IssueBaseInfo {
pub id: Uuid,
pub number: i64,
pub title: String,
pub state: State,
pub workspace_id: Uuid,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct PullRequestBaseInfo {
pub id: Uuid,
pub number: i64,
pub title: String,
pub state: State,
pub repo_id: Uuid,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct WikiPageBaseInfo {
pub id: Uuid,
pub title: String,
pub slug: String,
pub repo_id: Uuid,
}
// Section: DB row structs for batch queries
#[derive(Debug, sqlx::FromRow)]
struct UserBaseInfoRow {
id: Uuid,
username: String,
display_name: Option<String>,
avatar_url: Option<String>,
is_bot: bool,
}
impl From<UserBaseInfoRow> for UserBaseInfo {
fn from(r: UserBaseInfoRow) -> Self {
UserBaseInfo {
id: r.id,
username: r.username,
display_name: r.display_name,
avatar_url: r.avatar_url,
is_bot: r.is_bot,
}
}
}
#[derive(Debug, sqlx::FromRow)]
struct WorkspaceBaseInfoRow {
id: Uuid,
name: String,
avatar_url: Option<String>,
visibility: Visibility,
}
impl From<WorkspaceBaseInfoRow> for WorkspaceBaseInfo {
fn from(r: WorkspaceBaseInfoRow) -> Self {
WorkspaceBaseInfo {
id: r.id,
name: r.name,
avatar_url: r.avatar_url,
visibility: r.visibility,
}
}
}
#[derive(Debug, sqlx::FromRow)]
struct RepoBaseInfoRow {
id: Uuid,
name: String,
workspace_id: Uuid,
visibility: Visibility,
is_fork: bool,
}
impl From<RepoBaseInfoRow> for RepoBaseInfo {
fn from(r: RepoBaseInfoRow) -> Self {
RepoBaseInfo {
id: r.id,
name: r.name,
workspace_id: r.workspace_id,
visibility: r.visibility,
is_fork: r.is_fork,
}
}
}
#[derive(Debug, sqlx::FromRow)]
struct ChannelBaseInfoRow {
id: Uuid,
name: String,
channel_type: ChannelType,
workspace_id: Uuid,
archived: bool,
}
impl From<ChannelBaseInfoRow> for ChannelBaseInfo {
fn from(r: ChannelBaseInfoRow) -> Self {
ChannelBaseInfo {
id: r.id,
name: r.name,
channel_type: r.channel_type,
workspace_id: r.workspace_id,
archived: r.archived,
}
}
}
#[derive(Debug, sqlx::FromRow)]
struct IssueBaseInfoRow {
id: Uuid,
number: i64,
title: String,
state: State,
workspace_id: Uuid,
}
impl From<IssueBaseInfoRow> for IssueBaseInfo {
fn from(r: IssueBaseInfoRow) -> Self {
IssueBaseInfo {
id: r.id,
number: r.number,
title: r.title,
state: r.state,
workspace_id: r.workspace_id,
}
}
}
#[derive(Debug, sqlx::FromRow)]
struct PullRequestBaseInfoRow {
id: Uuid,
number: i64,
title: String,
state: State,
repo_id: Uuid,
}
impl From<PullRequestBaseInfoRow> for PullRequestBaseInfo {
fn from(r: PullRequestBaseInfoRow) -> Self {
PullRequestBaseInfo {
id: r.id,
number: r.number,
title: r.title,
state: r.state,
repo_id: r.repo_id,
}
}
}
impl UserBaseInfo {
pub fn placeholder(id: Uuid) -> Self {
Self {
id,
username: "unknown".into(),
display_name: Some("Unknown User".into()),
avatar_url: None,
is_bot: false,
}
}
}
// Section: Batch resolvers
/// Resolve multiple users to `UserBaseInfo`. Always do a single
/// `SELECT … WHERE id = ANY($1)` to avoid N+1.
pub async fn resolve_users(
db: &AppDatabase,
ids: &[Uuid],
) -> Result<HashMap<Uuid, UserBaseInfo>, AppError> {
if ids.is_empty() {
return Ok(HashMap::new());
}
let rows = sqlx::query_as::<_, UserBaseInfoRow>(
r#"SELECT id, username, display_name, avatar_url, is_bot
FROM "user" WHERE id = ANY($1) AND deleted_at IS NULL"#,
)
.bind(ids)
.fetch_all(db.reader())
.await
.map_err(AppError::Database)?;
Ok(rows.into_iter().map(|r| (r.id, r.into())).collect())
}
/// Resolve multiple workspaces to `WorkspaceBaseInfo`.
pub async fn resolve_workspaces(
db: &AppDatabase,
ids: &[Uuid],
) -> Result<HashMap<Uuid, WorkspaceBaseInfo>, AppError> {
if ids.is_empty() {
return Ok(HashMap::new());
}
let rows = sqlx::query_as::<_, WorkspaceBaseInfoRow>(
"SELECT id, name, avatar_url, visibility FROM workspace WHERE id = ANY($1) AND deleted_at IS NULL",
)
.bind(ids)
.fetch_all(db.reader())
.await
.map_err(AppError::Database)?;
Ok(rows.into_iter().map(|r| (r.id, r.into())).collect())
}
/// Resolve multiple repos to `RepoBaseInfo`.
pub async fn resolve_repos(
db: &AppDatabase,
ids: &[Uuid],
) -> Result<HashMap<Uuid, RepoBaseInfo>, AppError> {
if ids.is_empty() {
return Ok(HashMap::new());
}
let rows = sqlx::query_as::<_, RepoBaseInfoRow>(
"SELECT id, name, workspace_id, visibility, is_fork FROM repo WHERE id = ANY($1) AND deleted_at IS NULL",
)
.bind(ids)
.fetch_all(db.reader())
.await
.map_err(AppError::Database)?;
Ok(rows.into_iter().map(|r| (r.id, r.into())).collect())
}
/// Resolve multiple channels to `ChannelBaseInfo`.
pub async fn resolve_channels(
db: &AppDatabase,
ids: &[Uuid],
) -> Result<HashMap<Uuid, ChannelBaseInfo>, AppError> {
if ids.is_empty() {
return Ok(HashMap::new());
}
let rows = sqlx::query_as::<_, ChannelBaseInfoRow>(
"SELECT id, name, channel_type, workspace_id, archived FROM channel WHERE id = ANY($1) AND deleted_at IS NULL",
)
.bind(ids)
.fetch_all(db.reader())
.await
.map_err(AppError::Database)?;
Ok(rows.into_iter().map(|r| (r.id, r.into())).collect())
}
/// Resolve multiple issues to `IssueBaseInfo`.
pub async fn resolve_issues(
db: &AppDatabase,
ids: &[Uuid],
) -> Result<HashMap<Uuid, IssueBaseInfo>, AppError> {
if ids.is_empty() {
return Ok(HashMap::new());
}
let rows = sqlx::query_as::<_, IssueBaseInfoRow>(
"SELECT id, number, title, state, workspace_id FROM issue WHERE id = ANY($1) AND deleted_at IS NULL",
)
.bind(ids)
.fetch_all(db.reader())
.await
.map_err(AppError::Database)?;
Ok(rows.into_iter().map(|r| (r.id, r.into())).collect())
}
/// Resolve multiple pull requests to `PullRequestBaseInfo`.
pub async fn resolve_pull_requests(
db: &AppDatabase,
ids: &[Uuid],
) -> Result<HashMap<Uuid, PullRequestBaseInfo>, AppError> {
if ids.is_empty() {
return Ok(HashMap::new());
}
let rows = sqlx::query_as::<_, PullRequestBaseInfoRow>(
"SELECT id, number, title, state, repo_id FROM pull_request WHERE id = ANY($1) AND deleted_at IS NULL",
)
.bind(ids)
.fetch_all(db.reader())
.await
.map_err(AppError::Database)?;
Ok(rows.into_iter().map(|r| (r.id, r.into())).collect())
}
-18
View File
@@ -1,18 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Discussion comment on an article (similar to blog comments).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct ArticleComment {
pub id: Uuid,
pub article_id: Uuid,
pub channel_id: Uuid,
pub author_id: Uuid,
pub parent_comment_id: Option<Uuid>,
pub body: String,
pub edited_at: Option<DateTime<Utc>>,
pub deleted_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
-22
View File
@@ -1,22 +0,0 @@
use crate::models::common::Status;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Tracks a single cross-post delivery when an article is published
/// to a follower channel/workspace.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct ArticleCrossPost {
pub id: Uuid,
pub article_id: Uuid,
pub follow_id: Uuid,
pub target_workspace_id: Uuid,
pub target_channel_id: Option<Uuid>,
pub status: Status,
pub attempts: i32,
pub last_error: Option<String>,
pub sent_at: Option<DateTime<Utc>>,
pub delivered_at: Option<DateTime<Utc>>,
pub failed_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
}
-14
View File
@@ -1,14 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Reaction on an article (emoji reactions, separate from message reactions).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct ArticleReaction {
pub id: Uuid,
pub article_id: Uuid,
pub channel_id: Uuid,
pub user_id: Uuid,
pub content: String,
pub created_at: DateTime<Utc>,
}
-35
View File
@@ -1,35 +0,0 @@
use crate::models::common::{ArticleStatus, JsonValue, Visibility};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Long-form article for announcement/news channels.
/// Unlike a plain Message, an article has a title, cover image,
/// publish lifecycle, and can be cross-posted to followers.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct Article {
pub id: Uuid,
pub channel_id: Uuid,
pub author_id: Uuid,
pub title: String,
pub slug: String,
pub summary: Option<String>,
pub body: String,
pub cover_image_url: Option<String>,
pub status: ArticleStatus,
pub visibility: Visibility,
pub tags: Vec<String>,
pub published_at: Option<DateTime<Utc>>,
pub published_by: Option<Uuid>,
pub scheduled_at: Option<DateTime<Utc>>,
pub unpublished_at: Option<DateTime<Utc>>,
pub views_count: i64,
pub comments_count: i64,
pub reactions_count: i64,
pub cross_posted: bool,
pub cross_posted_from: Option<Uuid>,
pub metadata: Option<JsonValue>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
+63 -1
View File
@@ -1,3 +1,4 @@
use crate::models::base_info::UserBaseInfo;
use crate::models::common::{
ChannelKind, ChannelType, ForumLayout, ForumSortOrder, JsonValue, Visibility,
};
@@ -5,7 +6,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct Channel {
pub id: Uuid,
pub workspace_id: Uuid,
@@ -41,3 +42,64 @@ pub struct Channel {
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct ChannelDetail {
pub id: Uuid,
pub workspace_id: Uuid,
pub repo_id: Option<Uuid>,
pub category_id: Option<Uuid>,
pub creator: UserBaseInfo,
pub name: String,
pub topic: Option<String>,
pub description: Option<String>,
pub channel_type: ChannelType,
pub channel_kind: ChannelKind,
pub visibility: Visibility,
pub position: Option<i32>,
pub nsfw: bool,
pub archived: bool,
pub read_only: bool,
pub bitrate: Option<i32>,
pub user_limit: Option<i32>,
pub rtc_region: Option<String>,
pub parent_channel_id: Option<Uuid>,
pub last_message_id: Option<Uuid>,
pub last_message_at: Option<DateTime<Utc>>,
pub archived_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
impl Channel {
pub fn into_detail(self, creator: UserBaseInfo) -> ChannelDetail {
ChannelDetail {
id: self.id,
workspace_id: self.workspace_id,
repo_id: self.repo_id,
category_id: self.category_id,
creator,
name: self.name,
topic: self.topic,
description: self.description,
channel_type: self.channel_type,
channel_kind: self.channel_kind,
visibility: self.visibility,
position: self.position,
nsfw: self.nsfw,
archived: self.archived,
read_only: self.read_only,
bitrate: self.bitrate,
user_limit: self.user_limit,
rtc_region: self.rtc_region,
parent_channel_id: self.parent_channel_id,
last_message_id: self.last_message_id,
last_message_at: self.last_message_at,
archived_at: self.archived_at,
created_at: self.created_at,
updated_at: self.updated_at,
deleted_at: self.deleted_at,
}
}
}
+1 -1
View File
@@ -2,7 +2,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct ChannelCategory {
pub id: Uuid,
pub workspace_id: Uuid,
-23
View File
@@ -1,23 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Follow relationship on an announcement channel.
/// Allows another workspace or channel to receive cross-posts
/// when articles are published.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct ChannelFollow {
pub id: Uuid,
pub source_channel_id: Uuid,
pub target_workspace_id: Uuid,
pub target_channel_id: Option<Uuid>,
pub webhook_url: Option<String>,
pub webhook_secret_ciphertext: Option<String>,
pub enabled: bool,
pub followed_by: Uuid,
pub unfollowed_at: Option<DateTime<Utc>>,
pub last_delivery_at: Option<DateTime<Utc>>,
pub last_delivery_status: Option<String>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
+1 -1
View File
@@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct ChannelMember {
pub id: Uuid,
pub channel_id: Uuid,
@@ -1,4 +1,4 @@
use crate::models::common::{OverwriteTarget, Permission};
use crate::models::common::OverwriteTarget;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
@@ -9,8 +9,8 @@ pub struct ChannelPermissionOverwrite {
pub channel_id: Uuid,
pub target_type: OverwriteTarget,
pub target_id: Uuid,
pub allow: Vec<Permission>,
pub deny: Vec<Permission>,
pub allow: Vec<String>,
pub deny: Vec<String>,
pub created_by: Uuid,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
-23
View File
@@ -1,23 +0,0 @@
use crate::models::common::{JsonValue, MessageType};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct Message {
pub id: Uuid,
pub channel_id: Uuid,
pub author_id: Uuid,
pub thread_id: Option<Uuid>,
pub reply_to_message_id: Option<Uuid>,
pub seq: i64,
pub message_type: MessageType,
pub body: String,
pub metadata: Option<JsonValue>,
pub pinned: bool,
pub system: bool,
pub edited_at: Option<DateTime<Utc>>,
pub deleted_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
-21
View File
@@ -1,21 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageAttachment {
pub id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub filename: String,
pub url: String,
pub proxy_url: Option<String>,
pub size_bytes: i64,
pub mime_type: String,
pub width: Option<i32>,
pub height: Option<i32>,
pub duration_ms: Option<i64>,
pub thumbnail_url: Option<String>,
pub blurhash: Option<String>,
pub created_at: DateTime<Utc>,
}
-14
View File
@@ -1,14 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageBookmark {
pub id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub user_id: Uuid,
pub note: Option<String>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
-17
View File
@@ -1,17 +0,0 @@
use crate::models::common::JsonValue;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageDraft {
pub id: Uuid,
pub user_id: Uuid,
pub channel_id: Uuid,
pub thread_id: Option<Uuid>,
pub reply_to_message_id: Option<Uuid>,
pub content: String,
pub attachments: Option<JsonValue>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
-13
View File
@@ -1,13 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageEditHistory {
pub id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub previous_body: String,
pub edited_by: Uuid,
pub edited_at: DateTime<Utc>,
}
-34
View File
@@ -1,34 +0,0 @@
use crate::models::common::{EmbedType, JsonValue};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageEmbed {
pub id: Uuid,
pub message_id: Uuid,
pub embed_type: EmbedType,
pub title: Option<String>,
pub description: Option<String>,
pub url: Option<String>,
pub author_name: Option<String>,
pub author_url: Option<String>,
pub author_icon_url: Option<String>,
pub thumbnail_url: Option<String>,
pub thumbnail_width: Option<i32>,
pub thumbnail_height: Option<i32>,
pub image_url: Option<String>,
pub image_width: Option<i32>,
pub image_height: Option<i32>,
pub video_url: Option<String>,
pub video_width: Option<i32>,
pub video_height: Option<i32>,
pub color: Option<i32>,
pub fields: Option<JsonValue>,
pub footer_text: Option<String>,
pub footer_icon_url: Option<String>,
pub provider_name: Option<String>,
pub provider_url: Option<String>,
pub timestamp: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
}
-14
View File
@@ -1,14 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageMention {
pub id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub mentioned_user_id: Uuid,
pub mentioned_by: Uuid,
pub read_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
}
-12
View File
@@ -1,12 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessagePin {
pub id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub pinned_by: Uuid,
pub pinned_at: DateTime<Utc>,
}
-16
View File
@@ -1,16 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Poll option.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessagePollOption {
pub id: Uuid,
pub poll_id: Uuid,
pub position: i32,
pub text: String,
pub emoji_id: Option<String>,
pub emoji_name: Option<String>,
pub vote_count: i64,
pub created_at: DateTime<Utc>,
}
-13
View File
@@ -1,13 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// User vote record for a poll option.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessagePollVote {
pub id: Uuid,
pub poll_id: Uuid,
pub option_id: Uuid,
pub user_id: Uuid,
pub voted_at: DateTime<Utc>,
}
-22
View File
@@ -1,22 +0,0 @@
use crate::models::common::{JsonValue, PollLayout};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Message poll (similar to Discord Polls).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessagePoll {
pub id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub question: String,
pub description: Option<String>,
pub layout: PollLayout,
pub allow_multiselect: bool,
pub duration_hours: Option<i32>,
pub ends_at: Option<DateTime<Utc>>,
pub total_votes: i64,
pub metadata: Option<JsonValue>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
-13
View File
@@ -1,13 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageReaction {
pub id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub user_id: Uuid,
pub content: String,
pub created_at: DateTime<Utc>,
}
-27
View File
@@ -1,27 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageThread {
pub id: Uuid,
pub channel_id: Uuid,
pub root_message_id: Uuid,
pub created_by: Uuid,
pub replies_count: i64,
pub participants_count: i64,
pub last_reply_message_id: Option<Uuid>,
pub last_reply_at: Option<DateTime<Utc>>,
pub resolved: bool,
pub resolved_by: Option<Uuid>,
pub resolved_at: Option<DateTime<Utc>>,
// ── Forum post specific ──
pub title: Option<String>,
pub tags: Vec<String>,
pub pinned: bool,
pub locked: bool,
pub rate_limit_per_user: Option<i32>,
pub auto_archive_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
+1 -41
View File
@@ -1,11 +1,6 @@
pub mod article_comments;
pub mod article_cross_posts;
pub mod article_reactions;
pub mod articles;
pub mod channel;
pub mod channel_categories;
pub mod channel_events;
pub mod channel_follows;
pub mod channel_invitations;
pub mod channel_member_roles;
pub mod channel_members;
@@ -17,32 +12,12 @@ pub mod channel_webhooks;
pub mod custom_emojis;
pub mod forum_tags;
pub mod im_integrations;
pub mod message;
pub mod message_attachments;
pub mod message_bookmarks;
pub mod message_drafts;
pub mod message_edit_history;
pub mod message_embeds;
pub mod message_mentions;
pub mod message_pins;
pub mod message_poll_options;
pub mod message_poll_votes;
pub mod message_polls;
pub mod message_reactions;
pub mod message_threads;
pub mod saved_messages;
pub mod stages;
pub mod thread_read_states;
pub mod voice_participants;
pub use article_comments::ArticleComment;
pub use article_cross_posts::ArticleCrossPost;
pub use article_reactions::ArticleReaction;
pub use articles::Article;
pub use channel::Channel;
pub use channel::{Channel, ChannelDetail};
pub use channel_categories::ChannelCategory;
pub use channel_events::ChannelEvent;
pub use channel_follows::ChannelFollow;
pub use channel_invitations::ChannelInvitation;
pub use channel_member_roles::ChannelMemberRole;
pub use channel_members::ChannelMember;
@@ -54,20 +29,5 @@ pub use channel_webhooks::ChannelWebhook;
pub use custom_emojis::CustomEmoji;
pub use forum_tags::ForumTag;
pub use im_integrations::ImIntegration;
pub use message::Message;
pub use message_attachments::MessageAttachment;
pub use message_bookmarks::MessageBookmark;
pub use message_drafts::MessageDraft;
pub use message_edit_history::MessageEditHistory;
pub use message_embeds::MessageEmbed;
pub use message_mentions::MessageMention;
pub use message_pins::MessagePin;
pub use message_poll_options::MessagePollOption;
pub use message_poll_votes::MessagePollVote;
pub use message_polls::MessagePoll;
pub use message_reactions::MessageReaction;
pub use message_threads::MessageThread;
pub use saved_messages::SavedMessage;
pub use stages::Stage;
pub use thread_read_states::ThreadReadState;
pub use voice_participants::VoiceParticipant;
-13
View File
@@ -1,13 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct SavedMessage {
pub id: Uuid,
pub user_id: Uuid,
pub message_id: Uuid,
pub channel_id: Uuid,
pub note: Option<String>,
pub created_at: DateTime<Utc>,
}
-14
View File
@@ -1,14 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
pub struct ThreadReadState {
pub id: Uuid,
pub user_id: Uuid,
pub thread_id: Uuid,
pub channel_id: Uuid,
pub last_read_message_id: Option<Uuid>,
pub last_read_at: Option<DateTime<Utc>>,
pub updated_at: DateTime<Utc>,
}
+46
View File
@@ -1,3 +1,4 @@
use crate::models::base_info::UserBaseInfo;
use crate::models::common::{Priority, State, Visibility};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
@@ -23,3 +24,48 @@ pub struct Issue {
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct IssueDetail {
pub id: Uuid,
pub workspace_id: Uuid,
pub author: UserBaseInfo,
pub number: i64,
pub title: String,
pub body: Option<String>,
pub state: State,
pub priority: Priority,
pub visibility: Visibility,
pub locked: bool,
pub milestone_id: Option<Uuid>,
pub closed_by: Option<Uuid>,
pub closed_at: Option<DateTime<Utc>>,
pub due_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
impl Issue {
pub fn into_detail(self, author: UserBaseInfo) -> IssueDetail {
IssueDetail {
id: self.id,
workspace_id: self.workspace_id,
author,
number: self.number,
title: self.title,
body: self.body,
state: self.state,
priority: self.priority,
visibility: self.visibility,
locked: self.locked,
milestone_id: self.milestone_id,
closed_by: self.closed_by,
closed_at: self.closed_at,
due_at: self.due_at,
created_at: self.created_at,
updated_at: self.updated_at,
deleted_at: self.deleted_at,
}
}
}
+28
View File
@@ -1,3 +1,4 @@
use crate::models::base_info::UserBaseInfo;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
@@ -14,3 +15,30 @@ pub struct IssueComment {
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct IssueCommentDetail {
pub id: Uuid,
pub issue_id: Uuid,
pub author: UserBaseInfo,
pub reply_to_comment_id: Option<Uuid>,
pub body: String,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
impl IssueComment {
pub fn into_detail(self, author: UserBaseInfo) -> IssueCommentDetail {
IssueCommentDetail {
id: self.id,
issue_id: self.issue_id,
author,
reply_to_comment_id: self.reply_to_comment_id,
body: self.body,
created_at: self.created_at,
updated_at: self.updated_at,
deleted_at: self.deleted_at,
}
}
}
+2 -2
View File
@@ -15,9 +15,9 @@ pub mod issue_stats;
pub mod issue_subscribers;
pub mod issue_templates;
pub use issue::Issue;
pub use issue::{Issue, IssueDetail};
pub use issue_assignees::IssueAssignee;
pub use issue_comments::IssueComment;
pub use issue_comments::{IssueComment, IssueCommentDetail};
pub use issue_commit_relations::IssueCommitRelation;
pub use issue_events::IssueEvent;
pub use issue_label_relations::IssueLabelRelation;
+1
View File
@@ -1,5 +1,6 @@
pub mod agents;
pub mod ais;
pub mod base_info;
pub mod channels;
pub mod common;
pub mod conversations;
+1 -1
View File
@@ -4,7 +4,7 @@ pub mod notification_deliveries;
pub mod notification_subscriptions;
pub mod notification_templates;
pub use notification::Notification;
pub use notification::{Notification, NotificationDetail};
pub use notification_blocks::NotificationBlock;
pub use notification_deliveries::NotificationDelivery;
pub use notification_subscriptions::NotificationSubscription;
+64 -1
View File
@@ -1,10 +1,11 @@
use crate::models::base_info::{RepoBaseInfo, UserBaseInfo, WorkspaceBaseInfo};
use crate::models::common::{NotificationType, Priority, TargetType};
use crate::models::json_types::{NotificationMetadata, TypedJson};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct Notification {
pub id: Uuid,
pub user_id: Uuid,
@@ -24,8 +25,70 @@ pub struct Notification {
pub priority: Priority,
pub read_at: Option<DateTime<Utc>>,
pub dismissed_at: Option<DateTime<Utc>>,
#[schema(value_type = serde_json::Value)]
pub metadata: Option<TypedJson<NotificationMetadata>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct NotificationDetail {
pub id: Uuid,
pub user_id: Uuid,
pub actor: Option<UserBaseInfo>,
pub workspace: Option<WorkspaceBaseInfo>,
pub repo: Option<RepoBaseInfo>,
pub issue_id: Option<Uuid>,
pub pull_request_id: Option<Uuid>,
pub channel_id: Option<Uuid>,
pub message_id: Option<Uuid>,
pub notification_type: NotificationType,
pub title: String,
pub body: Option<String>,
pub target_type: Option<TargetType>,
pub target_id: Option<Uuid>,
pub action_url: Option<String>,
pub priority: Priority,
pub read_at: Option<DateTime<Utc>>,
pub dismissed_at: Option<DateTime<Utc>>,
#[schema(value_type = serde_json::Value)]
pub metadata: Option<TypedJson<NotificationMetadata>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
impl Notification {
pub fn into_detail(
self,
actor: Option<UserBaseInfo>,
workspace: Option<WorkspaceBaseInfo>,
repo: Option<RepoBaseInfo>,
) -> NotificationDetail {
NotificationDetail {
id: self.id,
user_id: self.user_id,
actor,
workspace,
repo,
issue_id: self.issue_id,
pull_request_id: self.pull_request_id,
channel_id: self.channel_id,
message_id: self.message_id,
notification_type: self.notification_type,
title: self.title,
body: self.body,
target_type: self.target_type,
target_id: self.target_id,
action_url: self.action_url,
priority: self.priority,
read_at: self.read_at,
dismissed_at: self.dismissed_at,
metadata: self.metadata,
created_at: self.created_at,
updated_at: self.updated_at,
deleted_at: self.deleted_at,
}
}
}
+1 -1
View File
@@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct NotificationBlock {
pub id: Uuid,
pub user_id: Uuid,
@@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct NotificationDelivery {
pub id: Uuid,
pub notification_id: Uuid,
@@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct NotificationSubscription {
pub id: Uuid,
pub user_id: Uuid,
@@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct NotificationTemplate {
pub id: Uuid,
pub key: String,
+6 -2
View File
@@ -9,8 +9,10 @@ pub mod pr_merge_strategy;
pub mod pr_reactions;
pub mod pr_review;
pub mod pr_review_comment;
pub mod pr_review_requests;
pub mod pr_status;
pub mod pr_subscriptions;
pub mod pr_templates;
pub mod pull_request;
pub mod pull_request_queries;
@@ -23,8 +25,10 @@ pub use pr_label_relations::PrLabelRelation;
pub use pr_labels::PrLabel;
pub use pr_merge_strategy::PrMergeStrategy;
pub use pr_reactions::PrReaction;
pub use pr_review::PrReview;
pub use pr_review::{PrReview, PrReviewDetail};
pub use pr_review_comment::PrReviewComment;
pub use pr_review_requests::PrReviewRequest;
pub use pr_status::PrStatus;
pub use pr_subscriptions::PrSubscription;
pub use pull_request::PullRequest;
pub use pr_templates::PrTemplate;
pub use pull_request::{PullRequest, PullRequestDetail};
+32
View File
@@ -1,3 +1,4 @@
use crate::models::base_info::UserBaseInfo;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
@@ -17,3 +18,34 @@ pub struct PrReview {
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct PrReviewDetail {
pub id: Uuid,
pub pull_request_id: Uuid,
pub author: UserBaseInfo,
pub state: String,
pub body: Option<String>,
pub dismissed: bool,
pub dismissed_by: Option<Uuid>,
pub dismissed_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
impl PrReview {
pub fn into_detail(self, author: UserBaseInfo) -> PrReviewDetail {
PrReviewDetail {
id: self.id,
pull_request_id: self.pull_request_id,
author,
state: self.state,
body: self.body,
dismissed: self.dismissed_at.is_some(),
dismissed_by: self.dismissed_by,
dismissed_at: self.dismissed_at,
created_at: self.created_at,
updated_at: self.updated_at,
}
}
}
+11
View File
@@ -0,0 +1,11 @@
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct PrReviewRequest {
pub id: Uuid,
pub pull_request_id: Uuid,
pub reviewer_id: Uuid,
pub requested_by: Uuid,
pub created_at: chrono::DateTime<chrono::Utc>,
}
+17
View File
@@ -0,0 +1,17 @@
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct PrTemplate {
pub id: Uuid,
pub repo_id: Uuid,
pub name: String,
pub description: Option<String>,
pub title_template: Option<String>,
pub body_template: String,
pub labels: Vec<String>,
pub active: bool,
pub created_by: Option<Uuid>,
pub created_at: chrono::DateTime<chrono::Utc>,
pub updated_at: chrono::DateTime<chrono::Utc>,
}
+58
View File
@@ -1,3 +1,4 @@
use crate::models::base_info::UserBaseInfo;
use crate::models::common::State;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
@@ -29,3 +30,60 @@ pub struct PullRequest {
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct PullRequestDetail {
pub id: Uuid,
pub repo_id: Uuid,
pub author: UserBaseInfo,
pub number: i64,
pub title: String,
pub body: Option<String>,
pub state: State,
pub source_repo_id: Uuid,
pub source_branch: String,
pub target_repo_id: Uuid,
pub target_branch: String,
pub base_commit_sha: Option<String>,
pub head_commit_sha: String,
pub merge_commit_sha: Option<String>,
pub draft: bool,
pub locked: bool,
pub merged_by: Option<Uuid>,
pub merged_at: Option<DateTime<Utc>>,
pub closed_by: Option<Uuid>,
pub closed_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
impl PullRequest {
pub fn into_detail(self, author: UserBaseInfo) -> PullRequestDetail {
PullRequestDetail {
id: self.id,
repo_id: self.repo_id,
author,
number: self.number,
title: self.title,
body: self.body,
state: self.state,
source_repo_id: self.source_repo_id,
source_branch: self.source_branch,
target_repo_id: self.target_repo_id,
target_branch: self.target_branch,
base_commit_sha: self.base_commit_sha,
head_commit_sha: self.head_commit_sha,
merge_commit_sha: self.merge_commit_sha,
draft: self.draft,
locked: self.locked,
merged_by: self.merged_by,
merged_at: self.merged_at,
closed_by: self.closed_by,
closed_at: self.closed_at,
created_at: self.created_at,
updated_at: self.updated_at,
deleted_at: self.deleted_at,
}
}
}
+3 -1
View File
@@ -10,6 +10,7 @@ pub mod repo_members;
pub mod repo_push_commit;
pub mod repo_push_lock;
pub mod repo_queries;
pub mod repo_release_assets;
pub mod repo_releases;
pub mod repo_stars;
pub mod repo_stats;
@@ -18,7 +19,7 @@ pub mod repo_watches;
pub mod repo_webhooks;
pub use branch_protection_rule::BranchProtectionRule;
pub use repo::Repo;
pub use repo::{Repo, RepoDetail};
pub use repo_branches::RepoBranch;
pub use repo_commit_comments::RepoCommitComment;
pub use repo_commit_statuses::RepoCommitStatus;
@@ -28,6 +29,7 @@ pub use repo_invitations::RepoInvitation;
pub use repo_members::RepoMember;
pub use repo_push_commit::RepoPushCommit;
pub use repo_push_lock::RepoPushLock;
pub use repo_release_assets::RepoReleaseAsset;
pub use repo_releases::RepoRelease;
pub use repo_stars::RepoStar;
pub use repo_stats::RepoStats;
+88
View File
@@ -1,3 +1,4 @@
use crate::models::base_info::{UserBaseInfo, WorkspaceBaseInfo};
use crate::models::common::{GitService, Status, Visibility};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
@@ -23,4 +24,91 @@ pub struct Repo {
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
#[sqlx(default)]
pub topics: Vec<String>,
#[sqlx(default)]
pub homepage: Option<String>,
#[sqlx(default)]
pub has_issues: bool,
#[sqlx(default)]
pub has_wiki: bool,
#[sqlx(default)]
pub has_pull_requests: bool,
#[sqlx(default)]
pub allow_forking: bool,
#[sqlx(default)]
pub allow_merge_commit: bool,
#[sqlx(default)]
pub allow_squash_merge: bool,
#[sqlx(default)]
pub allow_rebase_merge: bool,
#[sqlx(default)]
pub delete_branch_on_merge: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct RepoDetail {
pub id: Uuid,
pub workspace: WorkspaceBaseInfo,
pub owner: UserBaseInfo,
pub name: String,
pub description: Option<String>,
pub default_branch: String,
pub visibility: Visibility,
pub status: Status,
pub is_fork: bool,
pub forked_from_repo_id: Option<Uuid>,
pub storage_node_ids: Vec<Uuid>,
pub primary_storage_node_id: Uuid,
pub storage_path: String,
pub git_service: GitService,
pub archived_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
pub topics: Vec<String>,
pub homepage: Option<String>,
pub has_issues: bool,
pub has_wiki: bool,
pub has_pull_requests: bool,
pub allow_forking: bool,
pub allow_merge_commit: bool,
pub allow_squash_merge: bool,
pub allow_rebase_merge: bool,
pub delete_branch_on_merge: bool,
}
impl Repo {
pub fn into_detail(self, owner: UserBaseInfo, workspace: WorkspaceBaseInfo) -> RepoDetail {
RepoDetail {
id: self.id,
workspace,
owner,
name: self.name,
description: self.description,
default_branch: self.default_branch,
visibility: self.visibility,
status: self.status,
is_fork: self.is_fork,
forked_from_repo_id: self.forked_from_repo_id,
storage_node_ids: self.storage_node_ids,
primary_storage_node_id: self.primary_storage_node_id,
storage_path: self.storage_path,
git_service: self.git_service,
archived_at: self.archived_at,
created_at: self.created_at,
updated_at: self.updated_at,
deleted_at: self.deleted_at,
topics: self.topics,
homepage: self.homepage,
has_issues: self.has_issues,
has_wiki: self.has_wiki,
has_pull_requests: self.has_pull_requests,
allow_forking: self.allow_forking,
allow_merge_commit: self.allow_merge_commit,
allow_squash_merge: self.allow_squash_merge,
allow_rebase_merge: self.allow_rebase_merge,
delete_branch_on_merge: self.delete_branch_on_merge,
}
}
}
+19
View File
@@ -0,0 +1,19 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct RepoReleaseAsset {
pub id: Uuid,
pub release_id: Uuid,
pub filename: String,
pub size_bytes: i64,
pub mime_type: String,
pub storage_path: String,
pub url: Option<String>,
pub download_count: i64,
pub uploaded_by: Option<Uuid>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
+4
View File
@@ -19,4 +19,8 @@ pub struct User {
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
#[sqlx(default)]
pub restore_token_hash: Option<String>,
#[sqlx(default)]
pub restore_token_expires_at: Option<DateTime<Utc>>,
}
+1 -1
View File
@@ -2,7 +2,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct UserBlock {
pub blocker_id: Uuid,
pub blocked_id: Uuid,
+1 -1
View File
@@ -2,7 +2,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct UserFollow {
pub follower_id: Uuid,
pub following_id: Uuid,
+1 -1
View File
@@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct UserPresence {
pub id: Uuid,
pub user_id: Uuid,
+1 -1
View File
@@ -12,7 +12,7 @@ pub mod workspace_settings;
pub mod workspace_stats;
pub mod workspace_webhooks;
pub use workspace::Workspace;
pub use workspace::{Workspace, WorkspaceDetail};
pub use workspace_audit_logs::WorkspaceAuditLog;
pub use workspace_billing::WorkspaceBilling;
pub use workspace_custom_branding::WorkspaceCustomBranding;
+40
View File
@@ -1,3 +1,4 @@
use crate::models::base_info::UserBaseInfo;
use crate::models::common::{Status, Visibility};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
@@ -20,3 +21,42 @@ pub struct Workspace {
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct WorkspaceDetail {
pub id: Uuid,
pub owner: UserBaseInfo,
pub name: String,
pub description: Option<String>,
pub avatar_url: Option<String>,
pub visibility: Visibility,
pub plan: String,
pub status: Status,
pub default_role: String,
pub is_personal: bool,
pub archived_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
}
impl Workspace {
pub fn into_detail(self, owner: UserBaseInfo) -> WorkspaceDetail {
WorkspaceDetail {
id: self.id,
owner,
name: self.name,
description: self.description,
avatar_url: self.avatar_url,
visibility: self.visibility,
plan: self.plan,
status: self.status,
default_role: self.default_role,
is_personal: self.is_personal,
archived_at: self.archived_at,
created_at: self.created_at,
updated_at: self.updated_at,
deleted_at: self.deleted_at,
}
}
}