84 lines
2.3 KiB
Go
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
|
|
}
|