github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/teams/kbfs_test.go (about) 1 package teams 2 3 import ( 4 "crypto/rand" 5 "encoding/hex" 6 "testing" 7 "time" 8 9 "github.com/keybase/client/go/kbtest" 10 "github.com/keybase/client/go/libkb" 11 "github.com/keybase/client/go/protocol/keybase1" 12 "github.com/stretchr/testify/require" 13 "golang.org/x/net/context" 14 ) 15 16 func makeCryptKey(t *testing.T, gen int) keybase1.CryptKey { 17 var key [libkb.NaclDHKeysize]byte 18 _, err := rand.Read(key[:]) 19 require.NoError(t, err) 20 return keybase1.CryptKey{ 21 KeyGeneration: gen, 22 Key: key, 23 } 24 } 25 26 func makeTLFID(t *testing.T) keybase1.TLFID { 27 b, err := libkb.RandBytesWithSuffix(16, 0x16) 28 require.NoError(t, err) 29 return keybase1.TLFID(hex.EncodeToString(b)) 30 } 31 32 func TestKBFSUpgradeTeam(t *testing.T) { 33 tc := SetupTest(t, "team", 1) 34 defer tc.Cleanup() 35 36 ctx := context.TODO() 37 user, err := kbtest.CreateAndSignupFakeUser("team", tc.G) 38 require.NoError(t, err) 39 40 team, _, _, err := LookupOrCreateImplicitTeam(ctx, tc.G, user.Username, false) 41 require.NoError(t, err) 42 tlfID := makeTLFID(t) 43 t.Logf("TLFID: %s", tlfID) 44 require.NoError(t, team.AssociateWithTLFID(ctx, tlfID)) 45 team, err = Load(context.TODO(), tc.G, keybase1.LoadTeamArg{ 46 ID: team.ID, 47 ForceRepoll: true, 48 }) 49 require.NoError(t, err) 50 51 checkCryptKeys := func(tlfID keybase1.TLFID, cryptKeys []keybase1.CryptKey, 52 appType keybase1.TeamApplication) { 53 team, err = Load(context.TODO(), tc.G, keybase1.LoadTeamArg{ 54 ID: team.ID, 55 ForceRepoll: true, 56 }) 57 require.NoError(t, err) 58 resKeys := team.KBFSCryptKeys(ctx, appType) 59 require.Len(t, resKeys, len(cryptKeys)) 60 require.Equal(t, cryptKeys, resKeys) 61 require.Equal(t, tlfID, team.LatestKBFSTLFID()) 62 } 63 64 chatCryptKeys := []keybase1.CryptKey{ 65 makeCryptKey(t, 1), 66 makeCryptKey(t, 2), 67 makeCryptKey(t, 3), 68 } 69 require.NoError(t, team.AssociateWithTLFKeyset(ctx, tlfID, chatCryptKeys, keybase1.TeamApplication_CHAT)) 70 checkCryptKeys(tlfID, chatCryptKeys, keybase1.TeamApplication_CHAT) 71 72 kbfsCryptKeys := chatCryptKeys 73 kbfsCryptKeys = append(kbfsCryptKeys, makeCryptKey(t, 4)) 74 require.NoError(t, team.AssociateWithTLFKeyset(ctx, tlfID, kbfsCryptKeys, keybase1.TeamApplication_KBFS)) 75 checkCryptKeys(tlfID, kbfsCryptKeys, keybase1.TeamApplication_KBFS) 76 } 77 78 type testTimer struct { 79 waits int 80 } 81 82 func (t *testTimer) StartupWait(m libkb.MetaContext) (err error) { 83 time.Sleep(10 * time.Millisecond) 84 return nil 85 } 86 87 func (t *testTimer) LoopWait(m libkb.MetaContext, _ error) (err error) { 88 time.Sleep(10 * time.Millisecond) 89 t.waits++ 90 return nil 91 } 92 93 type unpinnedTLFAPIFaker struct { 94 res *unpinnedTLF 95 } 96 97 func (u *unpinnedTLFAPIFaker) getUnpinnedTLF(_ libkb.MetaContext) (res *unpinnedTLF, err error) { 98 ret := u.res 99 u.res = nil 100 return ret, nil 101 } 102 103 func TestTLFPinLoop(t *testing.T) { 104 105 _, tcs, cleanup := setupNTests(t, 1) 106 defer cleanup() 107 108 t.Logf("U0 creates A") 109 rootName, rootID := createTeam2(*tcs[0]) 110 tlfID := randomTlfID(t) 111 112 faker := &unpinnedTLFAPIFaker{ 113 res: &unpinnedTLF{ 114 Name: rootName.String(), 115 TeamID: rootID, 116 TlfID: tlfID, 117 }, 118 } 119 exitCh := make(chan error) 120 timer := &testTimer{} 121 122 pinner := &backgroundTLFPinner{ 123 timer: timer, 124 getUnpinnedTLF: faker.getUnpinnedTLF, 125 exitCh: exitCh, 126 } 127 128 m := libkb.NewMetaContextForTest(*tcs[0]) 129 130 go func() { _ = pinner.run(m) }() 131 err := <-exitCh 132 require.NoError(t, err) 133 require.Equal(t, timer.waits, 1) 134 135 team, err := Load(m.Ctx(), tcs[0].G, keybase1.LoadTeamArg{ 136 ID: rootID, 137 ForceRepoll: true, 138 }) 139 require.NoError(t, err) 140 require.Equal(t, team.KBFSTLFIDs(), []keybase1.TLFID{tlfID}) 141 } 142 143 type logoutTimer struct{} 144 145 func (t *logoutTimer) StartupWait(m libkb.MetaContext) (err error) { 146 return m.LogoutKillSecrets() 147 } 148 149 func (t *logoutTimer) LoopWait(m libkb.MetaContext, _ error) (err error) { 150 return nil 151 } 152 153 func TestTLFPinLoopLogout(t *testing.T) { 154 155 _, tcs, cleanup := setupNTests(t, 1) 156 defer cleanup() 157 158 faker := &unpinnedTLFAPIFaker{} 159 exitCh := make(chan error) 160 timer := &logoutTimer{} 161 162 pinner := &backgroundTLFPinner{ 163 timer: timer, 164 getUnpinnedTLF: faker.getUnpinnedTLF, 165 exitCh: exitCh, 166 } 167 168 m := libkb.NewMetaContextForTest(*tcs[0]) 169 170 go func() { _ = pinner.run(m) }() 171 err := <-exitCh 172 require.Error(t, err) 173 require.IsType(t, libkb.LoginRequiredError{}, err) 174 }