package console import ( "context" "encoding/json" "time" "github.com/carlosframework/platform/internal/dnsrec" "github.com/carlosframework/platform/internal/hostops" "github.com/carlosframework/platform/internal/mail" "github.com/carlosframework/platform/internal/objstore" ) // Purge teardown backends. Every call is a durable effect under the purge // operation (fresh ID per attempt); the effect's permit is what lets the // call through the guarded backend beneath. Methods a teardown never needs // refuse. Named private fields only; every interface method written out. type claimPurgeEffects struct{ h *hostops.OperationHandle } func (e claimPurgeEffects) run(ctx context.Context, resource, action string, inputs map[string]string, call func(context.Context) error) error { id, err := claimEffectID() if err != nil { return err } _, err = e.h.Runner(time.Now).Run(ctx, hostops.Effect{ID: id, Resource: resource, Action: action, Inputs: inputs}, func(ctx context.Context) (string, error) { if err := call(ctx); err != nil { return "", err } return "success", nil }) return err } type claimPurgeStore struct { raw objstore.Provisioner e claimPurgeEffects } var _ objstore.Provisioner = claimPurgeStore{} func (p claimPurgeStore) EnsureBucket(context.Context, string) (string, error) { return "", hostops.ErrContract } func (p claimPurgeStore) EnsureUser(context.Context, string, string, string, *objstore.DenyTag) (string, error) { return "", hostops.ErrContract } func (p claimPurgeStore) MintKey(context.Context, string) (string, string, error) { return "", "", hostops.ErrContract } func (p claimPurgeStore) DeleteKey(ctx context.Context, user, id string) error { return p.e.run(ctx, "iam-user:"+user, "delete-key", map[string]string{"user": user, "key": id}, func(ctx context.Context) error { return p.raw.DeleteKey(ctx, user, id) }) } func (p claimPurgeStore) ReapKeys(ctx context.Context, user string, keep []string) error { raw, err := json.Marshal(keep) if err != nil { return err } return p.e.run(ctx, "iam-user:"+user, "reap-keys", map[string]string{"user": user, "keep": string(raw)}, func(ctx context.Context) error { return p.raw.ReapKeys(ctx, user, keep) }) } func (p claimPurgeStore) EmptyBucket(ctx context.Context, bucket string) error { return p.e.run(ctx, "bucket:"+bucket, "empty", map[string]string{"bucket": bucket}, func(ctx context.Context) error { return p.raw.EmptyBucket(ctx, bucket) }) } func (p claimPurgeStore) DeleteBucket(ctx context.Context, bucket string) error { return p.e.run(ctx, "bucket:"+bucket, "delete", map[string]string{"bucket": bucket}, func(ctx context.Context) error { return p.raw.DeleteBucket(ctx, bucket) }) } func (p claimPurgeStore) DeleteUser(ctx context.Context, user string) error { return p.e.run(ctx, "iam-user:"+user, "delete-user", map[string]string{"user": user}, func(ctx context.Context) error { return p.raw.DeleteUser(ctx, user) }) } type claimPurgeScanner struct { raw objstore.Scanner e claimPurgeEffects } var _ objstore.Scanner = claimPurgeScanner{} func (p claimPurgeScanner) EnsureEnabled(context.Context, string) error { return hostops.ErrContract } func (p claimPurgeScanner) EnsureDisabled(ctx context.Context, bucket string) error { return p.e.run(ctx, "scanner:"+bucket, "disable", map[string]string{"bucket": bucket}, func(ctx context.Context) error { return p.raw.EnsureDisabled(ctx, bucket) }) } func (p claimPurgeScanner) Verdict(ctx context.Context, bucket, key, version string) (objstore.Verdict, error) { return p.raw.Verdict(ctx, bucket, key, version) } func (p claimPurgeScanner) Status(ctx context.Context, bucket, key string) (objstore.Verdict, objstore.ScanObject, error) { return p.raw.Status(ctx, bucket, key) } func (p claimPurgeScanner) Scan(context.Context, string, string, string, int64) (objstore.Verdict, bool, error) { return objstore.VerdictUnknown, false, hostops.ErrContract } func (p claimPurgeScanner) Enforcement() objstore.DenyTag { return p.raw.Enforcement() } func (p claimPurgeScanner) Capacity(ctx context.Context) (int, int, error) { return p.raw.Capacity(ctx) } func (p claimPurgeScanner) Provenance(ctx context.Context) (string, string, error) { return p.raw.Provenance(ctx) } type claimPurgeMail struct { raw mail.Provisioner e claimPurgeEffects } var _ mail.Provisioner = claimPurgeMail{} func (p claimPurgeMail) EnsureTenant(context.Context, string) error { return hostops.ErrContract } func (p claimPurgeMail) EnsureConfigSet(context.Context, string, string, string) error { return hostops.ErrContract } func (p claimPurgeMail) SetIdentityConfigSet(context.Context, string, string, string) error { return hostops.ErrContract } func (p claimPurgeMail) AssociateTenantResource(context.Context, string, string) error { return hostops.ErrContract } func (p claimPurgeMail) DisassociateTenantResource(ctx context.Context, tenant, resource string) error { return p.e.run(ctx, "ses-resource:"+resource, "disassociate", map[string]string{"tenant": tenant, "resource": resource}, func(ctx context.Context) error { return p.raw.DisassociateTenantResource(ctx, tenant, resource) }) } func (p claimPurgeMail) EnsureIdentity(context.Context, string, string, string, bool) (mail.Identity, error) { return mail.Identity{}, hostops.ErrContract } func (p claimPurgeMail) IdentityStatus(ctx context.Context, region, domain string) (mail.Status, error) { return p.raw.IdentityStatus(ctx, region, domain) } func (p claimPurgeMail) DeleteIdentity(ctx context.Context, region, domain string) error { return p.e.run(ctx, "email-domain:"+region+":"+domain, "delete-identity", map[string]string{"region": region, "domain": domain}, func(ctx context.Context) error { return p.raw.DeleteIdentity(ctx, region, domain) }) } func (p claimPurgeMail) EnsureUser(context.Context, string, string, []string, []string, []string) (string, error) { return "", hostops.ErrContract } func (p claimPurgeMail) MintKey(context.Context, string) (string, string, error) { return "", "", hostops.ErrContract } func (p claimPurgeMail) SetKeyActive(ctx context.Context, user, key string, active bool) error { if active { return hostops.ErrContract } return p.e.run(ctx, "iam-user:"+user, "deactivate-key", map[string]string{"user": user, "key": key}, func(ctx context.Context) error { return p.raw.SetKeyActive(ctx, user, key, false) }) } func (p claimPurgeMail) DeleteKey(ctx context.Context, user, id string) error { return p.e.run(ctx, "iam-user:"+user, "delete-key", map[string]string{"user": user, "key": id}, func(ctx context.Context) error { return p.raw.DeleteKey(ctx, user, id) }) } func (p claimPurgeMail) ReapKeys(ctx context.Context, user string, keep []string) error { raw, err := json.Marshal(keep) if err != nil { return err } return p.e.run(ctx, "iam-user:"+user, "reap-keys", map[string]string{"user": user, "keep": string(raw)}, func(ctx context.Context) error { return p.raw.ReapKeys(ctx, user, keep) }) } func (p claimPurgeMail) DeleteUser(ctx context.Context, user string) error { return p.e.run(ctx, "iam-user:"+user, "delete-user", map[string]string{"user": user}, func(ctx context.Context) error { return p.raw.DeleteUser(ctx, user) }) } type claimPurgeDNS struct { raw dnsrec.Writer e claimPurgeEffects } var _ dnsrec.Writer = claimPurgeDNS{} func (p claimPurgeDNS) DeleteRecord(ctx context.Context, record dnsrec.Record) error { raw, err := json.Marshal(record) if err != nil { return err } return p.e.run(ctx, "dns:"+record.Key(), "delete", map[string]string{"record": string(raw)}, func(ctx context.Context) error { return p.raw.DeleteRecord(ctx, record) }) } // EnsureRecord: teardown of one member rewrites a shared domain's records // for the remaining members. func (p claimPurgeDNS) EnsureRecord(ctx context.Context, record dnsrec.Record) error { raw, err := json.Marshal(record) if err != nil { return err } return p.e.run(ctx, "dns:"+record.Key(), "ensure", map[string]string{"record": string(raw)}, func(ctx context.Context) error { return p.raw.EnsureRecord(ctx, record) }) }