mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-04 10:21:40 +00:00
@@ -0,0 +1,206 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user