441 lines
15 KiB
Go
441 lines
15 KiB
Go
package dto
|
|
|
|
import (
|
|
"github.com/noteapp/backend/internal/domain/entities"
|
|
)
|
|
|
|
// ========== AUTH DTOs ==========
|
|
|
|
// RegisterRequest represents a registration request
|
|
type RegisterRequest struct {
|
|
Email string `json:"email" validate:"required,email"`
|
|
Username string `json:"username" validate:"required,min=3,max=20"`
|
|
Password string `json:"password" validate:"required,min=8"`
|
|
PasswordConfirm string `json:"password_confirm" validate:"required,eqfield=Password"`
|
|
FirstName string `json:"first_name" validate:"max=50"`
|
|
LastName string `json:"last_name" validate:"max=50"`
|
|
}
|
|
|
|
// LoginRequest represents a login request
|
|
type LoginRequest struct {
|
|
Email string `json:"email" validate:"required,email"`
|
|
Password string `json:"password" validate:"required"`
|
|
}
|
|
|
|
// LoginResponse represents a login response
|
|
type LoginResponse struct {
|
|
AccessToken string `json:"access_token"`
|
|
RefreshToken string `json:"refresh_token,omitempty"`
|
|
User *UserDTO `json:"user"`
|
|
ExpiresIn int `json:"expires_in"`
|
|
}
|
|
|
|
// AuthProviderDTO represents an OAuth/OIDC provider in API responses.
|
|
type AuthProviderDTO struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
AuthorizationURL string `json:"authorization_url,omitempty"`
|
|
TokenURL string `json:"token_url,omitempty"`
|
|
UserInfoURL string `json:"userinfo_url,omitempty"`
|
|
Scopes []string `json:"scopes"`
|
|
IDTokenClaim string `json:"id_token_claim,omitempty"`
|
|
IsActive bool `json:"is_active"`
|
|
}
|
|
|
|
// CreateAuthProviderRequest represents an OAuth/OIDC provider creation request.
|
|
type CreateAuthProviderRequest struct {
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
ClientID string `json:"client_id"`
|
|
ClientSecret string `json:"client_secret"`
|
|
AuthorizationURL string `json:"authorization_url"`
|
|
TokenURL string `json:"token_url"`
|
|
UserInfoURL string `json:"userinfo_url"`
|
|
Scopes []string `json:"scopes"`
|
|
IDTokenClaim string `json:"id_token_claim,omitempty"`
|
|
IsActive bool `json:"is_active"`
|
|
}
|
|
|
|
// FeatureFlagsDTO represents app-wide feature flags in API responses.
|
|
type FeatureFlagsDTO struct {
|
|
RegistrationEnabled bool `json:"registration_enabled"`
|
|
ProviderLoginEnabled bool `json:"provider_login_enabled"`
|
|
PublicSharingEnabled bool `json:"public_sharing_enabled"`
|
|
}
|
|
|
|
// UpdateFeatureFlagsRequest represents admin payload for feature flag updates.
|
|
type UpdateFeatureFlagsRequest struct {
|
|
RegistrationEnabled bool `json:"registration_enabled"`
|
|
ProviderLoginEnabled bool `json:"provider_login_enabled"`
|
|
PublicSharingEnabled bool `json:"public_sharing_enabled"`
|
|
}
|
|
|
|
// UserDTO represents a user in API responses
|
|
type UserDTO struct {
|
|
ID string `json:"id"`
|
|
Email string `json:"email"`
|
|
Username string `json:"username"`
|
|
FirstName string `json:"first_name"`
|
|
LastName string `json:"last_name"`
|
|
Avatar string `json:"avatar,omitempty"`
|
|
GroupIDs []string `json:"group_ids,omitempty"`
|
|
Permissions []string `json:"permissions,omitempty"`
|
|
EmailVerified bool `json:"email_verified"`
|
|
}
|
|
|
|
// NewUserDTO creates a DTO from a user entity
|
|
func NewUserDTO(user *entities.User) *UserDTO {
|
|
groupIDs := make([]string, 0, len(user.GroupIDs))
|
|
for _, groupID := range user.GroupIDs {
|
|
groupIDs = append(groupIDs, groupID.Hex())
|
|
}
|
|
|
|
return &UserDTO{
|
|
ID: user.ID.Hex(),
|
|
Email: user.Email,
|
|
Username: user.Username,
|
|
FirstName: user.FirstName,
|
|
LastName: user.LastName,
|
|
Avatar: user.Avatar,
|
|
GroupIDs: groupIDs,
|
|
Permissions: user.Permissions,
|
|
EmailVerified: user.EmailVerified,
|
|
}
|
|
}
|
|
|
|
// AdminUserDTO extends UserDTO with admin-visible fields
|
|
type AdminUserDTO struct {
|
|
*UserDTO
|
|
IsActive bool `json:"is_active"`
|
|
CreatedAt string `json:"created_at"`
|
|
}
|
|
|
|
// PermissionGroupDTO represents a permission group in API responses.
|
|
type PermissionGroupDTO struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Permissions []string `json:"permissions"`
|
|
IsSystem bool `json:"is_system"`
|
|
CreatedAt string `json:"created_at"`
|
|
UpdatedAt string `json:"updated_at"`
|
|
}
|
|
|
|
// CreatePermissionGroupRequest represents group creation input.
|
|
type CreatePermissionGroupRequest struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Permissions []string `json:"permissions"`
|
|
}
|
|
|
|
// UpdatePermissionGroupRequest represents group update input.
|
|
type UpdatePermissionGroupRequest struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Permissions []string `json:"permissions"`
|
|
}
|
|
|
|
// UpdateUserGroupsRequest represents user group assignment input.
|
|
type UpdateUserGroupsRequest struct {
|
|
GroupIDs []string `json:"group_ids"`
|
|
}
|
|
|
|
// NewAdminUserDTO creates an admin DTO from a user entity
|
|
func NewAdminUserDTO(user *entities.User) *AdminUserDTO {
|
|
return &AdminUserDTO{
|
|
UserDTO: NewUserDTO(user),
|
|
IsActive: user.IsActive,
|
|
CreatedAt: user.CreatedAt.Format("2006-01-02T15:04:05Z"),
|
|
}
|
|
}
|
|
|
|
// NewPermissionGroupDTO creates a DTO from a permission group entity.
|
|
func NewPermissionGroupDTO(group *entities.PermissionGroup) *PermissionGroupDTO {
|
|
return &PermissionGroupDTO{
|
|
ID: group.ID.Hex(),
|
|
Name: group.Name,
|
|
Description: group.Description,
|
|
Permissions: group.Permissions,
|
|
IsSystem: group.IsSystem,
|
|
CreatedAt: group.CreatedAt.Format("2006-01-02T15:04:05Z"),
|
|
UpdatedAt: group.UpdatedAt.Format("2006-01-02T15:04:05Z"),
|
|
}
|
|
}
|
|
|
|
// AddSpaceMemberRequest represents a request to add a member to a space
|
|
type AddSpaceMemberRequest struct {
|
|
UserID string `json:"user_id"`
|
|
}
|
|
|
|
// SpaceMemberDTO represents a member in a space
|
|
type SpaceMemberDTO struct {
|
|
UserID string `json:"user_id"`
|
|
Username string `json:"username"`
|
|
JoinedAt string `json:"joined_at"`
|
|
}
|
|
|
|
// UserOptionDTO is a lightweight user object for dropdowns
|
|
type UserOptionDTO struct {
|
|
ID string `json:"id"`
|
|
Username string `json:"username"`
|
|
}
|
|
|
|
// NewAuthProviderDTO creates a DTO from an auth provider entity.
|
|
func NewAuthProviderDTO(provider *entities.AuthProvider) *AuthProviderDTO {
|
|
return &AuthProviderDTO{
|
|
ID: provider.ID.Hex(),
|
|
Name: provider.Name,
|
|
Type: provider.Type,
|
|
AuthorizationURL: provider.AuthorizationURL,
|
|
TokenURL: provider.TokenURL,
|
|
UserInfoURL: provider.UserInfoURL,
|
|
Scopes: provider.Scopes,
|
|
IDTokenClaim: provider.IDTokenClaim,
|
|
IsActive: provider.IsActive,
|
|
}
|
|
}
|
|
|
|
// NewFeatureFlagsDTO creates a DTO from feature flags entity.
|
|
func NewFeatureFlagsDTO(flags *entities.FeatureFlags) *FeatureFlagsDTO {
|
|
if flags == nil {
|
|
flags = entities.NewDefaultFeatureFlags()
|
|
}
|
|
|
|
return &FeatureFlagsDTO{
|
|
RegistrationEnabled: flags.RegistrationEnabled,
|
|
ProviderLoginEnabled: flags.ProviderLoginEnabled,
|
|
PublicSharingEnabled: flags.PublicSharingEnabled,
|
|
}
|
|
}
|
|
|
|
// ========== SPACE DTOs ==========
|
|
|
|
// CreateSpaceRequest represents a space creation request
|
|
type CreateSpaceRequest struct {
|
|
Name string `json:"name" validate:"required,min=1,max=100"`
|
|
Description string `json:"description" validate:"max=500"`
|
|
Icon string `json:"icon,omitempty" validate:"max=20"`
|
|
IsPublic bool `json:"is_public"`
|
|
}
|
|
|
|
// SpaceDTO represents a space in API responses
|
|
type SpaceDTO struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
PermissionKey string `json:"permission_key"`
|
|
Description string `json:"description"`
|
|
Icon string `json:"icon,omitempty"`
|
|
OwnerID string `json:"owner_id"`
|
|
IsPublic bool `json:"is_public"`
|
|
CreatedAt string `json:"created_at"`
|
|
UpdatedAt string `json:"updated_at"`
|
|
}
|
|
|
|
// NewSpaceDTO creates a DTO from a space entity
|
|
func NewSpaceDTO(space *entities.Space) *SpaceDTO {
|
|
dto := &SpaceDTO{
|
|
ID: space.ID.Hex(),
|
|
Name: space.Name,
|
|
PermissionKey: entities.SpacePermissionToken(space.Name),
|
|
Description: space.Description,
|
|
Icon: space.Icon,
|
|
OwnerID: space.OwnerID.Hex(),
|
|
IsPublic: space.IsPublic,
|
|
CreatedAt: space.CreatedAt.Format("2006-01-02T15:04:05Z"),
|
|
UpdatedAt: space.UpdatedAt.Format("2006-01-02T15:04:05Z"),
|
|
}
|
|
return dto
|
|
}
|
|
|
|
// ========== NOTE DTOs ==========
|
|
|
|
// CreateNoteRequest represents a note creation request
|
|
type CreateNoteRequest struct {
|
|
Title string `json:"title" validate:"required,min=1,max=255"`
|
|
Description string `json:"description" validate:"max=500"`
|
|
Content string `json:"content"`
|
|
NotePassword string `json:"note_password,omitempty" validate:"omitempty,min=4,max=128"`
|
|
Tags []string `json:"tags"`
|
|
CategoryID *string `json:"category_id,omitempty"`
|
|
IsPinned bool `json:"is_pinned"`
|
|
IsFavorite bool `json:"is_favorite"`
|
|
IsPublic bool `json:"is_public"`
|
|
}
|
|
|
|
// UpdateNoteRequest represents a note update request
|
|
type UpdateNoteRequest struct {
|
|
Title string `json:"title" validate:"min=1,max=255"`
|
|
Description *string `json:"description,omitempty" validate:"omitempty,max=500"`
|
|
Content string `json:"content"`
|
|
NotePassword *string `json:"note_password,omitempty" validate:"omitempty,max=128"`
|
|
Tags []string `json:"tags"`
|
|
CategoryID *string `json:"category_id,omitempty"`
|
|
IsPinned *bool `json:"is_pinned"`
|
|
IsFavorite *bool `json:"is_favorite"`
|
|
IsPublic *bool `json:"is_public,omitempty"`
|
|
}
|
|
|
|
// UnlockNoteRequest represents a password unlock request for protected notes
|
|
type UnlockNoteRequest struct {
|
|
Password string `json:"password" validate:"required,min=1,max=128"`
|
|
}
|
|
|
|
// NoteDTO represents a note in API responses
|
|
type NoteDTO struct {
|
|
ID string `json:"id"`
|
|
SpaceID string `json:"space_id"`
|
|
CategoryID *string `json:"category_id,omitempty"`
|
|
Title string `json:"title"`
|
|
Description string `json:"description"`
|
|
Content string `json:"content"`
|
|
Tags []string `json:"tags"`
|
|
IsPinned bool `json:"is_pinned"`
|
|
IsFavorite bool `json:"is_favorite"`
|
|
IsPublic bool `json:"is_public"`
|
|
IsPasswordProtected bool `json:"is_password_protected"`
|
|
CreatedBy string `json:"created_by"`
|
|
UpdatedBy string `json:"updated_by"`
|
|
CreatedAt string `json:"created_at"`
|
|
UpdatedAt string `json:"updated_at"`
|
|
}
|
|
|
|
// NoteListItemDTO represents a lightweight note payload for list/tree endpoints
|
|
type NoteListItemDTO struct {
|
|
ID string `json:"id"`
|
|
SpaceID string `json:"space_id"`
|
|
CategoryID *string `json:"category_id,omitempty"`
|
|
Title string `json:"title"`
|
|
Description string `json:"description"`
|
|
IsPinned bool `json:"is_pinned"`
|
|
IsFavorite bool `json:"is_favorite"`
|
|
IsPublic bool `json:"is_public"`
|
|
IsPasswordProtected bool `json:"is_password_protected"`
|
|
UpdatedAt string `json:"updated_at"`
|
|
}
|
|
|
|
// NewNoteDTO creates a DTO from a note entity
|
|
func NewNoteDTO(note *entities.Note) *NoteDTO {
|
|
var categoryID *string
|
|
if note.CategoryID != nil {
|
|
id := note.CategoryID.Hex()
|
|
categoryID = &id
|
|
}
|
|
return &NoteDTO{
|
|
ID: note.ID.Hex(),
|
|
SpaceID: note.SpaceID.Hex(),
|
|
CategoryID: categoryID,
|
|
Title: note.Title,
|
|
Description: note.Description,
|
|
Content: note.Content,
|
|
Tags: note.Tags,
|
|
IsPinned: note.IsPinned,
|
|
IsFavorite: note.IsFavorite,
|
|
IsPublic: note.IsPublic,
|
|
IsPasswordProtected: note.IsPasswordProtected,
|
|
CreatedBy: note.CreatedBy.Hex(),
|
|
UpdatedBy: note.UpdatedBy.Hex(),
|
|
CreatedAt: note.CreatedAt.Format("2006-01-02T15:04:05Z"),
|
|
UpdatedAt: note.UpdatedAt.Format("2006-01-02T15:04:05Z"),
|
|
}
|
|
}
|
|
|
|
// NewNoteListItemDTO creates a lightweight DTO from a note entity
|
|
func NewNoteListItemDTO(note *entities.Note) *NoteListItemDTO {
|
|
var categoryID *string
|
|
if note.CategoryID != nil {
|
|
id := note.CategoryID.Hex()
|
|
categoryID = &id
|
|
}
|
|
|
|
return &NoteListItemDTO{
|
|
ID: note.ID.Hex(),
|
|
SpaceID: note.SpaceID.Hex(),
|
|
CategoryID: categoryID,
|
|
Title: note.Title,
|
|
Description: note.Description,
|
|
IsPinned: note.IsPinned,
|
|
IsFavorite: note.IsFavorite,
|
|
IsPublic: note.IsPublic,
|
|
IsPasswordProtected: note.IsPasswordProtected,
|
|
UpdatedAt: note.UpdatedAt.Format("2006-01-02T15:04:05Z"),
|
|
}
|
|
}
|
|
|
|
// ========== CATEGORY DTOs ==========
|
|
|
|
// CreateCategoryRequest represents a category creation request
|
|
type CreateCategoryRequest struct {
|
|
Name string `json:"name" validate:"required,min=1,max=100"`
|
|
Description string `json:"description" validate:"max=500"`
|
|
ParentID *string `json:"parent_id,omitempty"`
|
|
Icon string `json:"icon,omitempty" validate:"max=20"`
|
|
}
|
|
|
|
// UpdateCategoryRequest represents a category update request
|
|
type UpdateCategoryRequest struct {
|
|
Name string `json:"name" validate:"min=1,max=100"`
|
|
Description string `json:"description" validate:"max=500"`
|
|
Icon string `json:"icon,omitempty" validate:"max=20"`
|
|
}
|
|
|
|
// CategoryDTO represents a category in API responses
|
|
type CategoryDTO struct {
|
|
ID string `json:"id"`
|
|
SpaceID string `json:"space_id"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
ParentID *string `json:"parent_id,omitempty"`
|
|
Icon string `json:"icon,omitempty"`
|
|
Order int `json:"order"`
|
|
CreatedAt string `json:"created_at"`
|
|
UpdatedAt string `json:"updated_at"`
|
|
}
|
|
|
|
// CategoryTreeDTO represents a category with its subcategories and notes
|
|
type CategoryTreeDTO struct {
|
|
*CategoryDTO
|
|
Subcategories []*CategoryTreeDTO `json:"subcategories"`
|
|
Notes []*NoteListItemDTO `json:"notes"`
|
|
}
|
|
|
|
// NewCategoryDTO creates a DTO from a category entity
|
|
func NewCategoryDTO(category *entities.Category) *CategoryDTO {
|
|
var parentID *string
|
|
if category.ParentID != nil {
|
|
id := category.ParentID.Hex()
|
|
parentID = &id
|
|
}
|
|
return &CategoryDTO{
|
|
ID: category.ID.Hex(),
|
|
SpaceID: category.SpaceID.Hex(),
|
|
Name: category.Name,
|
|
Description: category.Description,
|
|
ParentID: parentID,
|
|
Icon: category.Icon,
|
|
Order: category.Order,
|
|
CreatedAt: category.CreatedAt.Format("2006-01-02T15:04:05Z"),
|
|
UpdatedAt: category.UpdatedAt.Format("2006-01-02T15:04:05Z"),
|
|
}
|
|
}
|
|
|
|
// ========== ERROR DTOs ==========
|
|
|
|
// ErrorResponse represents an error response
|
|
type ErrorResponse struct {
|
|
Error string `json:"error"`
|
|
Message string `json:"message"`
|
|
Code int `json:"code"`
|
|
}
|
|
|
|
// ValidationError represents a validation error
|
|
type ValidationError struct {
|
|
Field string `json:"field"`
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
// ValidationErrorResponse represents multiple validation errors
|
|
type ValidationErrorResponse struct {
|
|
Errors []ValidationError `json:"errors"`
|
|
}
|