mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-02 17:31:39 +00:00
207 lines
5.1 KiB
Go
207 lines
5.1 KiB
Go
package keeper
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
apiv1 "github.com/sonr-io/sonr/api/did/v1"
|
|
"github.com/sonr-io/sonr/x/did/types"
|
|
)
|
|
|
|
// GetAssertionByControllerAndSubject retrieves an assertion by controller and subject
|
|
// This uses the unique index for optimal performance
|
|
func (k Keeper) GetAssertionByControllerAndSubject(
|
|
ctx context.Context,
|
|
controller string,
|
|
subject string,
|
|
) (*apiv1.Assertion, error) {
|
|
// Use the unique index on (controller, subject)
|
|
return k.OrmDB.AssertionTable().GetByControllerSubject(ctx, controller, subject)
|
|
}
|
|
|
|
// GetAssertionsByController retrieves all assertions for a controller
|
|
func (k Keeper) GetAssertionsByController(
|
|
ctx context.Context,
|
|
controller string,
|
|
) ([]*apiv1.Assertion, error) {
|
|
var assertions []*apiv1.Assertion
|
|
|
|
// Use the index on controller
|
|
indexKey := apiv1.AssertionControllerSubjectIndexKey{}.WithController(controller)
|
|
iter, err := k.OrmDB.AssertionTable().List(ctx, indexKey)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to query assertions: %w", err)
|
|
}
|
|
defer iter.Close()
|
|
|
|
for iter.Next() {
|
|
assertion, err := iter.Value()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get assertion value: %w", err)
|
|
}
|
|
assertions = append(assertions, assertion)
|
|
}
|
|
|
|
return assertions, nil
|
|
}
|
|
|
|
// HasAssertion checks if an assertion exists for a given DID
|
|
func (k Keeper) HasAssertion(ctx context.Context, did string) bool {
|
|
_, err := k.OrmDB.AssertionTable().Get(ctx, did)
|
|
return err == nil
|
|
}
|
|
|
|
// ValidateAssertionUniqueness validates that a controller+subject combination is unique
|
|
func (k Keeper) ValidateAssertionUniqueness(
|
|
ctx context.Context,
|
|
controller string,
|
|
subject string,
|
|
) error {
|
|
existing, err := k.GetAssertionByControllerAndSubject(ctx, controller, subject)
|
|
if err == nil && existing != nil {
|
|
return fmt.Errorf("assertion already exists for controller=%s, subject=%s", controller, subject)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CreateAssertion creates a new assertion with uniqueness validation
|
|
func (k Keeper) CreateAssertion(
|
|
ctx context.Context,
|
|
did string,
|
|
controller string,
|
|
subject string,
|
|
publicKeyBase64 string,
|
|
didKind string,
|
|
) error {
|
|
sdkCtx := sdk.UnwrapSDKContext(ctx)
|
|
|
|
// Validate uniqueness
|
|
if err := k.ValidateAssertionUniqueness(ctx, controller, subject); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Create assertion
|
|
assertion := &apiv1.Assertion{
|
|
Did: did,
|
|
Controller: controller,
|
|
Subject: subject,
|
|
PublicKeyBase64: publicKeyBase64,
|
|
DidKind: didKind,
|
|
CreationBlock: sdkCtx.BlockHeight(),
|
|
}
|
|
|
|
// Insert into ORM
|
|
if err := k.OrmDB.AssertionTable().Insert(ctx, assertion); err != nil {
|
|
return fmt.Errorf("failed to store assertion: %w", err)
|
|
}
|
|
|
|
// Emit event
|
|
sdkCtx.EventManager().EmitEvent(
|
|
sdk.NewEvent(
|
|
"assertion_created",
|
|
sdk.NewAttribute("did", did),
|
|
sdk.NewAttribute("controller", controller),
|
|
sdk.NewAttribute("subject", subject),
|
|
sdk.NewAttribute("kind", didKind),
|
|
),
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
// UpdateAssertion updates an existing assertion
|
|
func (k Keeper) UpdateAssertion(
|
|
ctx context.Context,
|
|
did string,
|
|
publicKeyBase64 string,
|
|
) error {
|
|
// Get existing assertion
|
|
existing, err := k.OrmDB.AssertionTable().Get(ctx, did)
|
|
if err != nil {
|
|
return fmt.Errorf("assertion not found: %s", did)
|
|
}
|
|
|
|
// Update fields
|
|
existing.PublicKeyBase64 = publicKeyBase64
|
|
|
|
// Update in ORM
|
|
if err := k.OrmDB.AssertionTable().Update(ctx, existing); err != nil {
|
|
return fmt.Errorf("failed to update assertion: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DeleteAssertion removes an assertion
|
|
func (k Keeper) DeleteAssertion(ctx context.Context, did string) error {
|
|
// Check if assertion exists
|
|
existing, err := k.OrmDB.AssertionTable().Get(ctx, did)
|
|
if err != nil {
|
|
return fmt.Errorf("assertion not found: %s", did)
|
|
}
|
|
|
|
// Delete from ORM
|
|
if err := k.OrmDB.AssertionTable().Delete(ctx, existing); err != nil {
|
|
return fmt.Errorf("failed to delete assertion: %w", err)
|
|
}
|
|
|
|
sdkCtx := sdk.UnwrapSDKContext(ctx)
|
|
sdkCtx.EventManager().EmitEvent(
|
|
sdk.NewEvent(
|
|
"assertion_deleted",
|
|
sdk.NewAttribute("did", did),
|
|
sdk.NewAttribute("controller", existing.Controller),
|
|
sdk.NewAttribute("subject", existing.Subject),
|
|
),
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetAssertionStats returns statistics about assertions
|
|
func (k Keeper) GetAssertionStats(ctx context.Context) (*types.AssertionStats, error) {
|
|
stats := &types.AssertionStats{
|
|
TotalAssertions: 0,
|
|
EmailAssertions: 0,
|
|
TelAssertions: 0,
|
|
SonrAssertions: 0,
|
|
WebAuthnAssertions: 0,
|
|
OtherAssertions: 0,
|
|
}
|
|
|
|
// Iterate through all assertions
|
|
iter, err := k.OrmDB.AssertionTable().List(ctx, apiv1.AssertionPrimaryKey{})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list assertions: %w", err)
|
|
}
|
|
defer iter.Close()
|
|
|
|
for iter.Next() {
|
|
assertion, err := iter.Value()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
stats.TotalAssertions++
|
|
|
|
// Categorize by kind
|
|
switch assertion.DidKind {
|
|
case "email":
|
|
stats.EmailAssertions++
|
|
case "tel":
|
|
stats.TelAssertions++
|
|
case "sonr":
|
|
stats.SonrAssertions++
|
|
case "webauthn":
|
|
stats.WebAuthnAssertions++
|
|
default:
|
|
stats.OtherAssertions++
|
|
}
|
|
}
|
|
|
|
return stats, nil
|
|
}
|