package database import ( "context" "errors" "fmt" "strings" "git.toki-labs.com/toki/ariadne/internal/domain/organization" ) type IdentityMembership struct { UserID string OrganizationID organization.ID OrganizationSlug string OrganizationName string Role string } // LookupIdentity resolves the organizations available to a verified external // identity. Callers must verify the identity token before using issuer/subject. func (database *Database) LookupIdentity( ctx context.Context, issuer string, subject string, ) ([]IdentityMembership, error) { if database == nil || database.identityPool == nil { return nil, errors.New("identity database is not configured") } issuer = strings.TrimSpace(issuer) subject = strings.TrimSpace(subject) if issuer == "" || subject == "" { return nil, errors.New("identity issuer and subject are required") } rows, err := database.identityPool.Query(ctx, ` SELECT identity_user.id, organization.id, organization.slug, organization.name, membership.role FROM public.users identity_user JOIN public.organization_memberships membership ON membership.user_id = identity_user.id AND membership.removed_at IS NULL JOIN public.organizations organization ON organization.id = membership.organization_id WHERE identity_user.identity_issuer = $1 AND identity_user.identity_subject = $2 ORDER BY organization.slug `, issuer, subject) if err != nil { return nil, fmt.Errorf("lookup identity memberships: %w", err) } defer rows.Close() var memberships []IdentityMembership for rows.Next() { var ( membership IdentityMembership organizationID string ) if err := rows.Scan( &membership.UserID, &organizationID, &membership.OrganizationSlug, &membership.OrganizationName, &membership.Role, ); err != nil { return nil, fmt.Errorf("scan identity membership: %w", err) } parsedOrganizationID, err := organization.ParseID(organizationID) if err != nil { return nil, fmt.Errorf("parse identity organization: %w", err) } membership.OrganizationID = parsedOrganizationID memberships = append(memberships, membership) } if err := rows.Err(); err != nil { return nil, fmt.Errorf("iterate identity memberships: %w", err) } return memberships, nil }