gohorsejobs/backend/internal/services/appwrite_service.go
Tiago Yamamoto 841b1d780c feat: Email System, Avatar Upload, Email Templates UI, and Public Job Posting
- Backend: Email producer (LavinMQ), EmailService interface
- Backend: CRUD API for email_templates and email_settings
- Backend: avatar_url field in users table + UpdateMyProfile support
- Backend: StorageService for pre-signed URLs
- NestJS: Email consumer with Nodemailer and Handlebars
- Frontend: Email Templates admin pages (list/edit)
- Frontend: Updated profileApi.uploadAvatar with pre-signed URL flow
- Frontend: New /post-job public page (company registration + job creation wizard)
- Migrations: 027_create_email_system.sql, 028_add_avatar_url_to_users.sql
2025-12-26 12:21:34 -03:00

90 lines
2.3 KiB
Go

package services
import (
"context"
"encoding/json"
"fmt"
"os"
"time"
"github.com/appwrite/sdk-for-go/client"
"github.com/appwrite/sdk-for-go/databases"
)
type AppwriteConfig struct {
Endpoint string `json:"endpoint"`
ProjectID string `json:"projectId"`
APIKey string `json:"apiKey"`
DatabaseID string `json:"databaseId"`
CollectionID string `json:"collectionId"`
}
type AppwriteService struct {
credentialsService *CredentialsService
}
func NewAppwriteService(creds *CredentialsService) *AppwriteService {
return &AppwriteService{
credentialsService: creds,
}
}
// PushMessage pushes a message to Appwrite Database for Realtime sync
func (s *AppwriteService) PushMessage(ctx context.Context, msgID, convoID, senderID, content string) error {
config, err := s.getConfig(ctx)
if err != nil {
return fmt.Errorf("appwrite config error: %w", err)
}
if config.Endpoint == "" || config.ProjectID == "" {
return fmt.Errorf("appwrite not configured")
}
// Initialize Client
// sdk-for-go v0.16.x uses direct field assignment or AddHeader for config
cl := client.New()
cl.Endpoint = config.Endpoint
cl.AddHeader("X-Appwrite-Project", config.ProjectID)
cl.AddHeader("X-Appwrite-Key", config.APIKey)
db := databases.New(cl)
// Create Document
_, err = db.CreateDocument(
config.DatabaseID,
config.CollectionID,
msgID,
map[string]interface{}{
"conversation_id": convoID,
"sender_id": senderID,
"content": content,
"timestamp": time.Now().Format(time.RFC3339),
},
db.WithCreateDocumentPermissions([]string{}), // Optional permissions
)
if err != nil {
return fmt.Errorf("failed to push to appwrite: %w", err)
}
return nil
}
func (s *AppwriteService) getConfig(ctx context.Context) (*AppwriteConfig, error) {
// Try DB first
payload, err := s.credentialsService.GetDecryptedKey(ctx, "appwrite")
if err == nil && payload != "" {
var cfg AppwriteConfig
if err := json.Unmarshal([]byte(payload), &cfg); err == nil {
return &cfg, nil
}
}
// Fallback to Env
return &AppwriteConfig{
Endpoint: os.Getenv("APPWRITE_ENDPOINT"),
ProjectID: os.Getenv("APPWRITE_PROJECT_ID"),
APIKey: os.Getenv("APPWRITE_API_KEY"),
DatabaseID: os.Getenv("APPWRITE_DATABASE_ID"),
CollectionID: "messages", // Default if not set
}, nil
}