- Added configuration options for Stalwart hosted mail in .env.example. - Updated Docker Compose to include Stalwart service with health checks. - Introduced new API endpoints for managing mail domains and migration projects. - Enhanced Authentik blueprints for user enrollment and post-migration security. - Updated OAuth handling for Google and Microsoft migration processes. - Improved error handling and response structures in the mail API. - Added integration tests for email claiming and migration workflows.
111 lines
3.3 KiB
Go
111 lines
3.3 KiB
Go
package migration
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestBootstrapDriveDeltaGoogle(t *testing.T) {
|
|
client := mockGoogleHTTPClient(t, func(w http.ResponseWriter, r *http.Request) {
|
|
if strings.Contains(r.URL.Path, "/drive/v3/changes/startPageToken") {
|
|
_, _ = w.Write([]byte(`{"startPageToken":"start-123"}`))
|
|
return
|
|
}
|
|
http.NotFound(w, r)
|
|
})
|
|
|
|
d := NewDriveImporter(nil, nil).WithHTTPClient(client)
|
|
cursor := map[string]any{}
|
|
if err := d.bootstrapDriveDelta(context.Background(), "token", "google", cursor); err != nil {
|
|
t.Fatalf("bootstrap: %v", err)
|
|
}
|
|
if cursor["driveChangeToken"] != "start-123" {
|
|
t.Fatalf("token = %v", cursor["driveChangeToken"])
|
|
}
|
|
}
|
|
|
|
func TestHasDriveDeltaCursor(t *testing.T) {
|
|
d := &DriveImporter{}
|
|
job := &Job{CursorJSON: map[string]any{}}
|
|
if d.hasDriveDeltaCursor(job, "google") {
|
|
t.Fatal("expected no google token")
|
|
}
|
|
job.CursorJSON["driveChangeToken"] = "tok"
|
|
if !d.hasDriveDeltaCursor(job, "google") {
|
|
t.Fatal("expected google token")
|
|
}
|
|
job.CursorJSON = map[string]any{"driveDeltaLink": "https://graph.microsoft.com/delta"}
|
|
if !d.hasDriveDeltaCursor(job, "microsoft") {
|
|
t.Fatal("expected microsoft delta link")
|
|
}
|
|
}
|
|
|
|
func TestGoogleFileToDriveItem(t *testing.T) {
|
|
folder := googleFileToDriveItem(googleDriveFile{
|
|
ID: "f1", Name: "Docs", MimeType: "application/vnd.google-apps.folder", Parents: []string{"root"},
|
|
})
|
|
if !folder.IsFolder || folder.ParentID != "root" {
|
|
t.Fatalf("folder: %#v", folder)
|
|
}
|
|
|
|
slides := googleFileToDriveItem(googleDriveFile{
|
|
ID: "s1", Name: "Deck", MimeType: "application/vnd.google-apps.presentation",
|
|
})
|
|
if !slides.Export || slides.ExportExt != ".pptx" {
|
|
t.Fatalf("slides export: %#v", slides)
|
|
}
|
|
|
|
binary := googleFileToDriveItem(googleDriveFile{
|
|
ID: "b1", Name: "photo.png", MimeType: "image/png", Size: "1024",
|
|
})
|
|
if binary.Export || binary.Download == "" || binary.Size != 1024 {
|
|
t.Fatalf("binary file: %#v", binary)
|
|
}
|
|
}
|
|
|
|
func TestGraphDriveToItem(t *testing.T) {
|
|
item := graphDriveToItem("", graphDriveItem{
|
|
ID: "item-1",
|
|
Name: "report.pdf",
|
|
Size: 4096,
|
|
File: &struct{ MimeType string `json:"mimeType"` }{MimeType: "application/pdf"},
|
|
ParentReference: &struct {
|
|
ID string `json:"id"`
|
|
}{ID: "parent-1"},
|
|
})
|
|
if item.IsFolder || item.ParentID != "parent-1" || item.Download == "" {
|
|
t.Fatalf("file item: %#v", item)
|
|
}
|
|
|
|
folder := graphDriveToItem("", graphDriveItem{
|
|
ID: "dir-1", Name: "Shared", Folder: &struct{ ChildCount int `json:"childCount"` }{ChildCount: 2},
|
|
})
|
|
if !folder.IsFolder {
|
|
t.Fatalf("folder item: %#v", folder)
|
|
}
|
|
}
|
|
|
|
func TestResolveDriveRelPath(t *testing.T) {
|
|
d := &DriveImporter{}
|
|
store := NewImportedItemStoreMemory()
|
|
ctx := context.Background()
|
|
if err := store.MarkPath(ctx, "parent", "Projects"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := store.MarkPath(ctx, "file-1", "Projects/old-name.docx"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if got := d.resolveDriveRelPath(store, driveItem{ID: "file-1", Name: "ignored.docx"}); got != "Projects/old-name.docx" {
|
|
t.Fatalf("stored path wins: %q", got)
|
|
}
|
|
if got := d.resolveDriveRelPath(store, driveItem{ID: "new", Name: "readme.txt", ParentID: "parent"}); got != "Projects/readme.txt" {
|
|
t.Fatalf("parent path join: %q", got)
|
|
}
|
|
if got := d.resolveDriveRelPath(store, driveItem{ID: "orphan", Name: "solo.txt"}); got != "solo.txt" {
|
|
t.Fatalf("root file: %q", got)
|
|
}
|
|
}
|