ariadne/internal/platform/database/identity.go
2026-07-24 05:45:04 +09:00

84 lines
2.3 KiB
Go

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
}