feat: Enhance real-time collaboration features with user awareness and document sharing

- Added user information (UserID, UserName, UserAvatar) to Client struct for presence tracking.
- Implemented failure handling in the broadcastMessage function to manage send failures and disconnect clients if necessary.
- Introduced document ownership and sharing capabilities:
  - Added OwnerID and Is_Public fields to Document model.
  - Created DocumentShare model for managing document sharing with permissions.
  - Implemented functions for creating, listing, and managing document shares in the Postgres store.
- Added user management functionality:
  - Created User model and associated functions for user management in the Postgres store.
  - Implemented session management with token hashing for security.
- Updated database schema with migrations for users, sessions, and document shares.
- Enhanced frontend Yjs integration with awareness event logging for user connections and disconnections.
This commit is contained in:
M1ngdaXie
2026-01-03 12:59:53 -08:00
parent 37d89b13b9
commit 7f5f32179b
21 changed files with 2064 additions and 232 deletions

View File

@@ -14,14 +14,17 @@ const (
)
type Document struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Type DocumentType `json:"type"`
YjsState []byte `json:"-"` // Don't expose binary data in JSON
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Type DocumentType `json:"type"`
YjsState []byte `json:"-"`
OwnerID *uuid.UUID `json:"owner_id"` // NEW
Is_Public bool `json:"is_public"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type CreateDocumentRequest struct {
Name string `json:"name" binding:"required"`
Type DocumentType `json:"type" binding:"required"`

View File

@@ -0,0 +1,30 @@
package models
import (
"time"
"github.com/google/uuid"
)
type DocumentShare struct {
ID uuid.UUID `json:"id"`
DocumentID uuid.UUID `json:"document_id"`
UserID uuid.UUID `json:"user_id"`
Permission string `json:"permission"` // "view" or "edit"
CreatedAt time.Time `json:"created_at"`
CreatedBy *uuid.UUID `json:"created_by"`
}
type CreateShareRequest struct {
UserEmail string `json:"user_email" binding:"required"`
Permission string `json:"permission" binding:"required,oneof=view edit"`
}
type ShareListResponse struct {
Shares []DocumentShareWithUser `json:"shares"`
}
type DocumentShareWithUser struct {
DocumentShare
User User `json:"user"`
}

View File

@@ -0,0 +1,48 @@
package models
import (
"time"
"github.com/google/uuid"
)
type User struct {
ID uuid.UUID `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
AvatarURL *string `json:"avatar_url"`
Provider string `json:"provider"`
ProviderUserID string `json:"-"` // Don't expose
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LastLoginAt *time.Time `json:"last_login_at"`
}
type Session struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"user_id"`
TokenHash string `json:"-"` // SHA-256 hash of JWT
ExpiresAt time.Time `json:"expires_at"`
CreatedAt time.Time `json:"created_at"`
UserAgent *string `json:"user_agent"`
IPAddress *string `json:"ip_address"`
}
type OAuthToken struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"user_id"`
Provider string `json:"provider"`
AccessToken string `json:"-"` // Don't expose
RefreshToken *string `json:"-"`
TokenType string `json:"token_type"`
ExpiresAt time.Time `json:"expires_at"`
Scope *string `json:"scope"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// Response for /auth/me endpoint
type UserResponse struct {
User *User `json:"user"`
Token string `json:"token,omitempty"`
}