github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/systests/wot_test.go (about)

     1  package systests
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/keybase/client/go/client"
     7  	"github.com/keybase/client/go/libkb"
     8  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
     9  	"github.com/keybase/client/go/service"
    10  	"github.com/stretchr/testify/require"
    11  	context "golang.org/x/net/context"
    12  )
    13  
    14  func TestWotNotifications(t *testing.T) {
    15  	tt := newTeamTester(t)
    16  	defer tt.cleanup()
    17  
    18  	alice := tt.addUser("alice")
    19  	bob := tt.addUser("bob")
    20  	tt.logUserNames()
    21  	iui := newSimpleIdentifyUI()
    22  	attachIdentifyUI(t, bob.tc.G, iui)
    23  	iui.confirmRes = keybase1.ConfirmResult{IdentityConfirmed: true, RemoteConfirmed: true, AutoConfirmed: true}
    24  	bob.track(alice.username)
    25  	iui = newSimpleIdentifyUI()
    26  	attachIdentifyUI(t, alice.tc.G, iui)
    27  	iui.confirmRes = keybase1.ConfirmResult{IdentityConfirmed: true, RemoteConfirmed: true, AutoConfirmed: true}
    28  	alice.track(bob.username)
    29  	var err error
    30  
    31  	getWotUpdate := func(user *userPlusDevice) keybase1.WotUpdate {
    32  		pollForTrue(t, user.tc.G, func(i int) bool {
    33  			badges := getBadgeState(t, user)
    34  			return len(badges.WotUpdates) > 0
    35  		})
    36  		badgeState := getBadgeState(t, user)
    37  		wotUpdates := badgeState.WotUpdates
    38  		require.Equal(t, 1, len(wotUpdates))
    39  		for _, w := range wotUpdates {
    40  			return w
    41  		}
    42  		t.Fail()
    43  		return keybase1.WotUpdate{}
    44  	}
    45  
    46  	dismiss := func(user *userPlusDevice) {
    47  		wotHandler := service.NewWebOfTrustHandler(nil, user.tc.G)
    48  		err := wotHandler.DismissWotNotifications(context.TODO(), keybase1.DismissWotNotificationsArg{
    49  			Voucher: alice.username,
    50  			Vouchee: bob.username,
    51  		})
    52  		require.NoError(t, err)
    53  		pollForTrue(t, user.tc.G, func(i int) bool {
    54  			badges := getBadgeState(t, user)
    55  			return len(badges.WotUpdates) == 0
    56  		})
    57  	}
    58  	aliceVouchesForBob := func() {
    59  		cli := &client.CmdWotVouch{
    60  			Contextified: libkb.NewContextified(alice.tc.G),
    61  			Assertion:    bob.username,
    62  			Message:      "whatever whatever",
    63  			Confidence: keybase1.Confidence{
    64  				UsernameVerifiedVia: keybase1.UsernameVerificationType_IN_PERSON,
    65  			},
    66  		}
    67  		err := cli.Run()
    68  		require.NoError(t, err)
    69  	}
    70  	bobAccepts := func() {
    71  		cli := &client.CmdWotAccept{
    72  			Contextified: libkb.NewContextified(bob.tc.G),
    73  			Voucher:      alice.username,
    74  		}
    75  		err := cli.Run()
    76  		require.NoError(t, err)
    77  	}
    78  
    79  	// alice vouches for bob - bob gets a notification
    80  	aliceVouchesForBob()
    81  	wotUpdate := getWotUpdate(bob)
    82  	require.Equal(t, wotUpdate.Status, keybase1.WotStatusType_PROPOSED)
    83  	require.Equal(t, wotUpdate.Voucher, alice.username)
    84  	require.Equal(t, wotUpdate.Vouchee, bob.username)
    85  	dismiss(bob)
    86  
    87  	// bob accepts - alice gets a notification
    88  	bobAccepts()
    89  	wotUpdate = getWotUpdate(alice)
    90  	require.Equal(t, wotUpdate.Status, keybase1.WotStatusType_ACCEPTED)
    91  	require.Equal(t, wotUpdate.Voucher, alice.username)
    92  	require.Equal(t, wotUpdate.Vouchee, bob.username)
    93  	dismiss(alice)
    94  
    95  	// bob rejects - alice gets a notification
    96  	cliR := &client.CmdWotReject{
    97  		Contextified: libkb.NewContextified(bob.tc.G),
    98  		Voucher:      alice.username,
    99  	}
   100  	err = cliR.Run()
   101  	require.NoError(t, err)
   102  	wotUpdate = getWotUpdate(alice)
   103  	require.Equal(t, wotUpdate.Status, keybase1.WotStatusType_REJECTED)
   104  	require.Equal(t, wotUpdate.Voucher, alice.username)
   105  	require.Equal(t, wotUpdate.Vouchee, bob.username)
   106  	dismiss(alice)
   107  
   108  	// notifications also go away if the underlying vouch was touched (i.e. implicit interaction)
   109  	// by the person being notified.
   110  	// 1. alice vouches for bob
   111  	aliceVouchesForBob()
   112  	// 2. bob has a notification
   113  	pollForTrue(t, bob.tc.G, func(i int) bool {
   114  		badges := getBadgeState(t, bob)
   115  		var wotUpdate keybase1.WotUpdate
   116  		for _, w := range badges.WotUpdates {
   117  			wotUpdate = w
   118  			break
   119  		}
   120  		return len(badges.WotUpdates) == 1 && wotUpdate.Status == keybase1.WotStatusType_PROPOSED
   121  	})
   122  	// 3. bob reacts
   123  	bobAccepts()
   124  	// 4. bob's notification is dismissed automatically
   125  	pollForTrue(t, bob.tc.G, func(i int) bool {
   126  		badges := getBadgeState(t, bob)
   127  		return len(badges.WotUpdates) == 0
   128  	})
   129  
   130  	// vouch_with_revoke resets the state of the attestation to PROPOSED
   131  	aliceVouchesForBob()
   132  	bobAccepts()
   133  	aliceVouchesForBob()
   134  	wotUpdate = getWotUpdate(bob)
   135  	require.Equal(t, wotUpdate.Status, keybase1.WotStatusType_PROPOSED)
   136  	require.Equal(t, wotUpdate.Voucher, alice.username)
   137  	require.Equal(t, wotUpdate.Vouchee, bob.username)
   138  }