first commit
This commit is contained in:
165
backend/internal/calendar/attachments.go
Normal file
165
backend/internal/calendar/attachments.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package calendar
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
var ErrAttachmentNotFound = errors.New("attachment not found")
|
||||
|
||||
type Attachment struct {
|
||||
ID string `json:"id"`
|
||||
CalendarItemID string `json:"calendar_item_id"`
|
||||
OriginalFilename string `json:"original_filename"`
|
||||
StoredFilename string `json:"stored_filename"`
|
||||
MimeType string `json:"mime_type"`
|
||||
SizeBytes int64 `json:"size_bytes"`
|
||||
StorageDriver string `json:"storage_driver"`
|
||||
StoragePath string `json:"-"`
|
||||
CreatedBy *string `json:"created_by"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type CreateAttachmentInput struct {
|
||||
CalendarItemID string
|
||||
OriginalFilename string
|
||||
StoredFilename string
|
||||
MimeType string
|
||||
SizeBytes int64
|
||||
StorageDriver string
|
||||
StoragePath string
|
||||
CreatedBy string
|
||||
}
|
||||
|
||||
func (s Store) CreateAttachment(ctx context.Context, input CreateAttachmentInput) (Attachment, error) {
|
||||
row := s.db.QueryRow(ctx, `
|
||||
INSERT INTO calendar_item_attachments (
|
||||
calendar_item_id,
|
||||
original_filename,
|
||||
stored_filename,
|
||||
mime_type,
|
||||
size_bytes,
|
||||
storage_driver,
|
||||
storage_path,
|
||||
created_by
|
||||
)
|
||||
VALUES ($1::uuid, $2, $3, $4, $5, $6, $7, NULLIF($8, '')::uuid)
|
||||
RETURNING
|
||||
id::text,
|
||||
calendar_item_id::text,
|
||||
original_filename,
|
||||
stored_filename,
|
||||
mime_type,
|
||||
size_bytes,
|
||||
storage_driver,
|
||||
storage_path,
|
||||
created_by::text,
|
||||
created_at
|
||||
`, input.CalendarItemID, input.OriginalFilename, input.StoredFilename, input.MimeType, input.SizeBytes, input.StorageDriver, input.StoragePath, input.CreatedBy)
|
||||
|
||||
return scanAttachment(row)
|
||||
}
|
||||
|
||||
func (s Store) ListAttachments(ctx context.Context, calendarItemID string, viewerUserID string) ([]Attachment, error) {
|
||||
rows, err := s.db.Query(ctx, `
|
||||
SELECT
|
||||
calendar_item_attachments.id::text,
|
||||
calendar_item_attachments.calendar_item_id::text,
|
||||
calendar_item_attachments.original_filename,
|
||||
calendar_item_attachments.stored_filename,
|
||||
calendar_item_attachments.mime_type,
|
||||
calendar_item_attachments.size_bytes,
|
||||
calendar_item_attachments.storage_driver,
|
||||
calendar_item_attachments.storage_path,
|
||||
calendar_item_attachments.created_by::text,
|
||||
calendar_item_attachments.created_at
|
||||
FROM calendar_item_attachments
|
||||
INNER JOIN calendar_items ON calendar_items.id = calendar_item_attachments.calendar_item_id
|
||||
WHERE calendar_item_attachments.calendar_item_id = $1::uuid
|
||||
AND (
|
||||
$2 = ''
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM client_users
|
||||
WHERE client_users.client_id = calendar_items.client_id
|
||||
AND client_users.user_id = $2::uuid
|
||||
)
|
||||
)
|
||||
ORDER BY calendar_item_attachments.created_at DESC
|
||||
`, calendarItemID, viewerUserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
attachments := []Attachment{}
|
||||
for rows.Next() {
|
||||
attachment, err := scanAttachment(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attachments = append(attachments, attachment)
|
||||
}
|
||||
|
||||
return attachments, rows.Err()
|
||||
}
|
||||
|
||||
func (s Store) FindAttachment(ctx context.Context, id string, viewerUserID string) (Attachment, error) {
|
||||
row := s.db.QueryRow(ctx, `
|
||||
SELECT
|
||||
calendar_item_attachments.id::text,
|
||||
calendar_item_attachments.calendar_item_id::text,
|
||||
calendar_item_attachments.original_filename,
|
||||
calendar_item_attachments.stored_filename,
|
||||
calendar_item_attachments.mime_type,
|
||||
calendar_item_attachments.size_bytes,
|
||||
calendar_item_attachments.storage_driver,
|
||||
calendar_item_attachments.storage_path,
|
||||
calendar_item_attachments.created_by::text,
|
||||
calendar_item_attachments.created_at
|
||||
FROM calendar_item_attachments
|
||||
INNER JOIN calendar_items ON calendar_items.id = calendar_item_attachments.calendar_item_id
|
||||
WHERE calendar_item_attachments.id = $1::uuid
|
||||
AND (
|
||||
$2 = ''
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM client_users
|
||||
WHERE client_users.client_id = calendar_items.client_id
|
||||
AND client_users.user_id = $2::uuid
|
||||
)
|
||||
)
|
||||
`, id, viewerUserID)
|
||||
|
||||
return scanAttachment(row)
|
||||
}
|
||||
|
||||
type attachmentScanner interface {
|
||||
Scan(dest ...any) error
|
||||
}
|
||||
|
||||
func scanAttachment(row attachmentScanner) (Attachment, error) {
|
||||
var attachment Attachment
|
||||
err := row.Scan(
|
||||
&attachment.ID,
|
||||
&attachment.CalendarItemID,
|
||||
&attachment.OriginalFilename,
|
||||
&attachment.StoredFilename,
|
||||
&attachment.MimeType,
|
||||
&attachment.SizeBytes,
|
||||
&attachment.StorageDriver,
|
||||
&attachment.StoragePath,
|
||||
&attachment.CreatedBy,
|
||||
&attachment.CreatedAt,
|
||||
)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return Attachment{}, ErrAttachmentNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return Attachment{}, err
|
||||
}
|
||||
return attachment, nil
|
||||
}
|
||||
Reference in New Issue
Block a user