add gitlab ci
This commit is contained in:
@@ -41,6 +41,7 @@ type FileRow struct {
|
||||
FolderID string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
OcrText string
|
||||
}
|
||||
|
||||
type FolderRow struct {
|
||||
@@ -156,11 +157,11 @@ func (r *Resources) InsertFolder(ownerID, id, name, parentResourceID string) err
|
||||
return r.insert(ownerID, id, name, parentResourceID, "folder", 0, nil, nil)
|
||||
}
|
||||
|
||||
const fileColumns = `resource_id, name, size_bytes, COALESCE(mime_type, ''), COALESCE(parent_id, ''), created_at, updated_at`
|
||||
const fileColumns = `resource_id, name, size_bytes, COALESCE(mime_type, ''), COALESCE(parent_id, ''), created_at, updated_at, COALESCE(ocr_text, '')`
|
||||
|
||||
func (r *Resources) scanFile(scan func(...any) error) (FileRow, error) {
|
||||
var row FileRow
|
||||
err := scan(&row.ID, &row.Name, &row.Size, &row.MimeType, &row.FolderID, &row.CreatedAt, &row.UpdatedAt)
|
||||
err := scan(&row.ID, &row.Name, &row.Size, &row.MimeType, &row.FolderID, &row.CreatedAt, &row.UpdatedAt, &row.OcrText)
|
||||
return row, err
|
||||
}
|
||||
|
||||
@@ -471,6 +472,29 @@ func (r *Resources) UpdatePhysical(ownerID, resourceID string, size int64, mimeT
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateOcrText writes the server-computed OCR extract onto the resource
|
||||
// (owner-scoped, bumping updated_at so the change flows through the sync
|
||||
// snapshot). The text is then readable by every device of the user AND by
|
||||
// grantees via GET /files/:id/ocr (viewer+, cf. docs/api-v1.md §5).
|
||||
func (r *Resources) UpdateOcrText(ownerID, resourceID, text string) error {
|
||||
result, err := r.DB.Exec(
|
||||
`UPDATE resources SET ocr_text = $3, updated_at = NOW()
|
||||
WHERE resource_id = $1 AND user_id = $2 AND type = 'file' AND deleted_at IS NULL`,
|
||||
resourceID, ownerID, text,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
affected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if affected == 0 {
|
||||
return ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SyncDelete soft-deletes a resource; absence is NOT an error (idempotent
|
||||
// terminal state for the outbox).
|
||||
func (r *Resources) SyncDelete(ownerID, resourceID string) error {
|
||||
|
||||
@@ -232,3 +232,54 @@ func TestListOwnedDelta(t *testing.T) {
|
||||
t.Errorf("delta attendu uniquement fresh.txt, got %+v", delta)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateOcrTextAndReadBack(t *testing.T) {
|
||||
repo := newTestResources(t)
|
||||
owner := NewID()
|
||||
other := NewID()
|
||||
mustInsertUser(t, repo, owner)
|
||||
mustInsertUser(t, repo, other)
|
||||
|
||||
fileID := NewID()
|
||||
if err := repo.InsertFile(owner, fileID, "scan.png", "", 128, nil, nil); err != nil {
|
||||
t.Fatalf("insert file: %v", err)
|
||||
}
|
||||
|
||||
// Vide par défaut.
|
||||
before := time.Now()
|
||||
row, err := repo.GetFile(owner, fileID)
|
||||
if err != nil {
|
||||
t.Fatalf("get file: %v", err)
|
||||
}
|
||||
if row.OcrText != "" {
|
||||
t.Errorf("ocr_text initial = %q, attendu vide", row.OcrText)
|
||||
}
|
||||
|
||||
if err := repo.UpdateOcrText(owner, fileID, "extrait du scan"); err != nil {
|
||||
t.Fatalf("update ocr_text: %v", err)
|
||||
}
|
||||
|
||||
// L'exécution bump updated_at (→ delta outbox/snapshot).
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
after, err := repo.GetFile(owner, fileID)
|
||||
if err != nil {
|
||||
t.Fatalf("get file après : %v", err)
|
||||
}
|
||||
if after.OcrText != "extrait du scan" {
|
||||
t.Errorf("ocr_text = %q, attendu %q", after.OcrText, "extrait du scan")
|
||||
}
|
||||
if !after.UpdatedAt.After(before) {
|
||||
t.Errorf("updated_at non bumpé: before=%v after=%v", before, after.UpdatedAt)
|
||||
}
|
||||
if after.UpdatedAt.Before(time.Now().Add(-time.Minute)) {
|
||||
t.Errorf("updated_at incohérent: %v", after.UpdatedAt)
|
||||
}
|
||||
|
||||
// Non-owner / ressource inconnue → ErrNotFound.
|
||||
if err := repo.UpdateOcrText(other, fileID, "volé"); !errors.Is(err, ErrNotFound) {
|
||||
t.Errorf("autre user : attendu ErrNotFound, got %v", err)
|
||||
}
|
||||
if err := repo.UpdateOcrText(owner, NewID(), "x"); !errors.Is(err, ErrNotFound) {
|
||||
t.Errorf("inconnue : attendu ErrNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user