package users import ( "context" "fmt" "atlas9.dev/c/core/dbi" "atlas9.dev/c/core/iam" "atlas9.dev/c/demo/lib" "atlas9.dev/c/demo/store" ) type Provisioner struct { Tenants dbi.Factory[iam.TenantStore] TenantMembers dbi.Factory[iam.TenantMemberStore] Grants dbi.Factory[iam.GrantStore] Profiles dbi.Factory[*store.ProfileStore] } func (p *Provisioner) Provision(ctx context.Context, tx dbi.DBI, user *iam.User) error { tenants := p.Tenants(tx) members := p.TenantMembers(tx) grants := p.Grants(tx) profiles := p.Profiles(tx) // TODO interesting case of the system needing access ctx = lib.PutSystemAccess(ctx, iam.CapTenantsCreate, iam.CapTenantMembersCreate, iam.CapUsersVerify, iam.CapGrantsAdd, iam.CapProfilesSave, ) // Create profile profile := store.Profile{ UserID: user.ID, Name: "", Bio: "", Location: "", Website: "", PictureURL: "", } if err := profiles.Save(ctx, &profile); err != nil { return fmt.Errorf("creating profile: %w", err) } // Create personal tenant tenant := iam.Tenant{ ID: user.ID, Name: user.Email, // TODO tenant name shouldn't leak an email. } member := iam.TenantMember{ Tenant: user.ID, UserID: user.ID, Owner: true, } if err := tenants.Create(ctx, &tenant); err != nil { return fmt.Errorf("creating personal tenant: %w", err) } if err := members.Create(ctx, member); err != nil { return fmt.Errorf("adding tenant membership: %w", err) } // Grant owner role on personal tenant if err := grants.Add(ctx, iam.Grant{ Tenant: user.ID, Type: iam.GrantTypeUser, Principal: user.ID.String(), Role: "owner", }); err != nil { return fmt.Errorf("granting owner role: %w", err) } return nil }