//go:build integration package migration_test import ( "context" "net/http" "net/http/httptest" "net/url" "strings" "testing" "github.com/google/uuid" "github.com/jackc/pgx/v5/pgxpool" "github.com/ultisuite/ulti-backend/internal/integrationtest" "github.com/ultisuite/ulti-backend/internal/mail/credentials" "github.com/ultisuite/ulti-backend/internal/nextcloud" "github.com/ultisuite/ulti-backend/internal/users" ) func mockNextcloudServer(t *testing.T) *httptest.Server { t.Helper() return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodPut, "MKCOL", "MKCALENDAR": w.WriteHeader(http.StatusCreated) case http.MethodDelete: w.WriteHeader(http.StatusNoContent) case "PROPFIND", "REPORT", http.MethodGet: w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(``)) default: w.WriteHeader(http.StatusNoContent) } })) } func testCredentialManager(t *testing.T) *credentials.Manager { t.Helper() mgr, err := credentials.NewManager( "v1:MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=", "v1", ) if err != nil { t.Fatalf("credential manager: %v", err) } return mgr } func mockNextcloudClient(t *testing.T, pool *pgxpool.Pool, email string) (*nextcloud.Client, string) { t.Helper() srv := mockNextcloudServer(t) t.Cleanup(srv.Close) ncUserID := nextcloud.UserIDFromClaims(email, "") store := nextcloud.NewDAVCredentialStore(pool, testCredentialManager(t)) if err := store.SaveToken(context.Background(), ncUserID, "mock-app-password"); err != nil { t.Fatalf("seed dav token: %v", err) } client := nextcloud.NewClient(srv.URL, "admin", "admin").WithDAVCredentials(store) return client, ncUserID } func insertMigrationTestUser(t *testing.T, pool *pgxpool.Pool, prefix string) (userID, email string) { t.Helper() claims := integrationtest.RegularUser(integrationtest.NewExternalID(prefix)) claims.Email = prefix + "-" + uuid.NewString() + "@migration.test" id, err := users.EnsureUser(context.Background(), pool, claims) integrationtest.FailIf(err, t, "ensure user") return id, claims.Email } func googleRewriteClient(t *testing.T, handler http.HandlerFunc) *http.Client { t.Helper() srv := httptest.NewServer(handler) t.Cleanup(srv.Close) return &http.Client{ Transport: &hostRewriteTransport{ mockBase: srv.URL, match: func(host string) bool { return strings.Contains(host, "googleapis.com") }, }, } } func graphRewriteClient(t *testing.T, handler http.HandlerFunc) *http.Client { t.Helper() srv := httptest.NewServer(handler) t.Cleanup(srv.Close) return &http.Client{ Transport: &hostRewriteTransport{ mockBase: srv.URL, match: func(host string) bool { return strings.Contains(host, "graph.microsoft.com") }, }, } } type hostRewriteTransport struct { mockBase string match func(host string) bool } func (rt *hostRewriteTransport) RoundTrip(req *http.Request) (*http.Response, error) { if rt.match(req.URL.Host) { mockURL, err := url.Parse(rt.mockBase) if err != nil { return nil, err } req.URL.Scheme = mockURL.Scheme req.URL.Host = mockURL.Host } return http.DefaultTransport.RoundTrip(req) }