first commit
Made-with: Cursor
This commit is contained in:
52
internal/models/errors.go
Normal file
52
internal/models/errors.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type AppError struct {
|
||||
Status int `json:"-"`
|
||||
Code string `json:"code"`
|
||||
Message string `json:"error"`
|
||||
Details string `json:"details,omitempty"`
|
||||
}
|
||||
|
||||
func (e *AppError) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
var (
|
||||
ErrAuthRequired = &AppError{Status: http.StatusUnauthorized, Code: "AUTH_REQUIRED", Message: "Authentication required"}
|
||||
ErrAuthInvalid = &AppError{Status: http.StatusUnauthorized, Code: "AUTH_INVALID", Message: "Invalid credentials"}
|
||||
ErrForbidden = &AppError{Status: http.StatusForbidden, Code: "FORBIDDEN", Message: "Permission denied"}
|
||||
ErrNotFound = &AppError{Status: http.StatusNotFound, Code: "NOT_FOUND", Message: "Resource not found"}
|
||||
ErrValidation = &AppError{Status: http.StatusBadRequest, Code: "VALIDATION_ERROR", Message: "Validation failed"}
|
||||
ErrConflict = &AppError{Status: http.StatusConflict, Code: "CONFLICT", Message: "Resource conflict"}
|
||||
ErrRateLimited = &AppError{Status: http.StatusTooManyRequests, Code: "RATE_LIMITED", Message: "Too many requests"}
|
||||
ErrInternal = &AppError{Status: http.StatusInternalServerError, Code: "INTERNAL", Message: "Internal server error"}
|
||||
)
|
||||
|
||||
func NewValidationError(detail string) *AppError {
|
||||
return &AppError{Status: http.StatusBadRequest, Code: "VALIDATION_ERROR", Message: "Validation failed", Details: detail}
|
||||
}
|
||||
|
||||
func NewConflictError(detail string) *AppError {
|
||||
return &AppError{Status: http.StatusConflict, Code: "CONFLICT", Message: detail}
|
||||
}
|
||||
|
||||
func NewNotFoundError(detail string) *AppError {
|
||||
return &AppError{Status: http.StatusNotFound, Code: "NOT_FOUND", Message: detail}
|
||||
}
|
||||
|
||||
func NewForbiddenError(detail string) *AppError {
|
||||
return &AppError{Status: http.StatusForbidden, Code: "FORBIDDEN", Message: detail}
|
||||
}
|
||||
|
||||
func IsAppError(err error) (*AppError, bool) {
|
||||
var appErr *AppError
|
||||
if errors.As(err, &appErr) {
|
||||
return appErr, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
164
internal/models/models.go
Normal file
164
internal/models/models.go
Normal file
@@ -0,0 +1,164 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Email string `json:"email"`
|
||||
Timezone string `json:"timezone"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Calendar struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Color string `json:"color"`
|
||||
IsPublic bool `json:"is_public"`
|
||||
Role string `json:"role,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
CalendarID uuid.UUID `json:"calendar_id"`
|
||||
Title string `json:"title"`
|
||||
Description *string `json:"description"`
|
||||
Location *string `json:"location"`
|
||||
StartTime time.Time `json:"start_time"`
|
||||
EndTime time.Time `json:"end_time"`
|
||||
Timezone string `json:"timezone"`
|
||||
AllDay bool `json:"all_day"`
|
||||
RecurrenceRule *string `json:"recurrence_rule"`
|
||||
IsOccurrence bool `json:"is_occurrence,omitempty"`
|
||||
OccurrenceStartTime *time.Time `json:"occurrence_start_time,omitempty"`
|
||||
OccurrenceEndTime *time.Time `json:"occurrence_end_time,omitempty"`
|
||||
CreatedBy uuid.UUID `json:"created_by"`
|
||||
UpdatedBy uuid.UUID `json:"updated_by"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Reminders []Reminder `json:"reminders"`
|
||||
Attendees []Attendee `json:"attendees"`
|
||||
Tags []string `json:"tags"`
|
||||
Attachments []Attachment `json:"attachments"`
|
||||
}
|
||||
|
||||
type Reminder struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
MinutesBefore int32 `json:"minutes_before"`
|
||||
}
|
||||
|
||||
type Attendee struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
UserID *uuid.UUID `json:"user_id"`
|
||||
Email *string `json:"email"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type Attachment struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
FileURL string `json:"file_url"`
|
||||
}
|
||||
|
||||
type Contact struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
FirstName *string `json:"first_name"`
|
||||
LastName *string `json:"last_name"`
|
||||
Email *string `json:"email"`
|
||||
Phone *string `json:"phone"`
|
||||
Company *string `json:"company"`
|
||||
Notes *string `json:"notes"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type APIKeyResponse struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
RevokedAt *time.Time `json:"revoked_at"`
|
||||
Token string `json:"token,omitempty"`
|
||||
}
|
||||
|
||||
type CalendarMember struct {
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
Email string `json:"email"`
|
||||
Role string `json:"role"`
|
||||
}
|
||||
|
||||
type BusyBlock struct {
|
||||
Start time.Time `json:"start"`
|
||||
End time.Time `json:"end"`
|
||||
EventID uuid.UUID `json:"event_id"`
|
||||
}
|
||||
|
||||
type AvailabilityResponse struct {
|
||||
CalendarID uuid.UUID `json:"calendar_id"`
|
||||
RangeStart time.Time `json:"range_start"`
|
||||
RangeEnd time.Time `json:"range_end"`
|
||||
Busy []BusyBlock `json:"busy"`
|
||||
}
|
||||
|
||||
type BookingLink struct {
|
||||
Token string `json:"token"`
|
||||
PublicURL string `json:"public_url,omitempty"`
|
||||
Settings BookingConfig `json:"settings"`
|
||||
}
|
||||
|
||||
type BookingConfig struct {
|
||||
DurationMinutes int `json:"duration_minutes"`
|
||||
BufferMinutes int `json:"buffer_minutes"`
|
||||
Timezone string `json:"timezone"`
|
||||
WorkingHours map[string][]Slot `json:"working_hours"`
|
||||
Active bool `json:"active"`
|
||||
}
|
||||
|
||||
type Slot struct {
|
||||
Start string `json:"start"`
|
||||
End string `json:"end"`
|
||||
}
|
||||
|
||||
type BookingAvailability struct {
|
||||
Token string `json:"token"`
|
||||
Timezone string `json:"timezone"`
|
||||
DurationMinutes int `json:"duration_minutes"`
|
||||
Slots []TimeSlot `json:"slots"`
|
||||
}
|
||||
|
||||
type TimeSlot struct {
|
||||
Start time.Time `json:"start"`
|
||||
End time.Time `json:"end"`
|
||||
}
|
||||
|
||||
type PageInfo struct {
|
||||
Limit int `json:"limit"`
|
||||
NextCursor *string `json:"next_cursor"`
|
||||
}
|
||||
|
||||
type ListResponse struct {
|
||||
Items interface{} `json:"items"`
|
||||
Page PageInfo `json:"page"`
|
||||
}
|
||||
|
||||
type AuthTokens struct {
|
||||
User User `json:"user"`
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
||||
|
||||
type TokenPair struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
||||
|
||||
type AuditEntry struct {
|
||||
EntityType string `json:"entity_type"`
|
||||
EntityID uuid.UUID `json:"entity_id"`
|
||||
Action string `json:"action"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
}
|
||||
Reference in New Issue
Block a user