github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/teams/rename_test.go (about) 1 package teams 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/keybase/client/go/kbtest" 8 "github.com/keybase/client/go/protocol/keybase1" 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestRenameSimple(t *testing.T) { 13 tc := SetupTest(t, "team", 1) 14 defer tc.Cleanup() 15 16 u, err := kbtest.CreateAndSignupFakeUser("t", tc.G) 17 require.NoError(t, err) 18 19 parentTeamName, err := keybase1.TeamNameFromString(u.Username + "T") 20 require.NoError(t, err) 21 _, err = CreateRootTeam(context.TODO(), tc.G, parentTeamName.String(), keybase1.TeamSettings{}) 22 require.NoError(t, err) 23 24 subteamBasename := "bb1" 25 subteamID, err := CreateSubteam(context.TODO(), tc.G, subteamBasename, parentTeamName, keybase1.TeamRole_NONE /* addSelfAs */) 26 require.NoError(t, err) 27 subteamName, err := parentTeamName.Append(subteamBasename) 28 require.NoError(t, err) 29 desiredName, err := parentTeamName.Append("bb2") 30 require.NoError(t, err) 31 32 err = RenameSubteam(context.TODO(), tc.G, subteamName, desiredName) 33 require.NoError(t, err) 34 35 t.Logf("load the renamed team") 36 subteam, err := Load(context.TODO(), tc.G, keybase1.LoadTeamArg{ 37 ID: *subteamID, 38 ForceRepoll: true, 39 }) 40 require.NoError(t, err) 41 require.Equal(t, parentTeamName.String()+".bb2", subteam.Name().String(), "new name") 42 43 t.Logf("load the parent") 44 parent, err := Load(context.TODO(), tc.G, keybase1.LoadTeamArg{ 45 Name: parentTeamName.String(), 46 NeedAdmin: true, 47 ForceRepoll: true, 48 }) 49 require.NoError(t, err) 50 subteamList := parent.chain().ListSubteams() 51 require.Len(t, subteamList, 1, "has 1 subteam") 52 require.Equal(t, subteamList[0].Name.String(), parentTeamName.String()+".bb2") 53 require.Equal(t, subteamList[0].Id.String(), subteamID.String()) 54 require.Len(t, parent.chain().inner.SubteamLog, 1, "subteam log has 1 series") 55 require.Len(t, parent.chain().inner.SubteamLog[*subteamID], 2, "subteam log has 2 entries") 56 } 57 58 // This was a bug that once caused the loader to get stuck. 59 // - Create team A 60 // - Create team A.B1 61 // - Create team A.B1.C <new_subteam> 62 // - Rename A.B1 -> A.B2 (implicitly renaming A.B1.C -> A.B2.C) 63 // - Someone else (U1) loads A.B2 with <new_subteam> stubbed 64 // - Add U1 as an admin of A.B2 or as a member of A.B2's subtree. 65 // - U1 loads and inflates <new_subteam>. 66 // The last step failed because the new_subteam link says A.B1.C 67 // but that doesn't look like a valid subteam name of A.B2. 68 func TestRenameInflateSubteamAfterRenameParent(t *testing.T) { 69 fus, tcs, cleanup := setupNTests(t, 2) 70 defer cleanup() 71 72 t.Logf("U0 creates A") 73 parentName, _ := createTeam2(*tcs[0]) 74 75 subteamName1 := createTeamName(t, parentName.String(), "bb1") 76 subteamName2 := createTeamName(t, parentName.String(), "bb2") 77 subsubteamName2 := createTeamName(t, parentName.String(), "bb2", "cc") 78 79 t.Logf("U0 creates A.B1") 80 subteamID, err := CreateSubteam(context.TODO(), tcs[0].G, "bb1", parentName, keybase1.TeamRole_NONE /* addSelfAs */) 81 require.NoError(t, err) 82 83 t.Logf("U0 creates A.B1.C") 84 subsubteamID, err := CreateSubteam(context.TODO(), tcs[0].G, "cc", subteamName1, keybase1.TeamRole_NONE /* addSelfAs */) 85 require.NoError(t, err) 86 87 t.Logf("U0 adds U1 to A.B1 as a writer") 88 _, err = AddMember(context.TODO(), tcs[0].G, subteamName1.String(), fus[1].Username, keybase1.TeamRole_WRITER, nil) 89 require.NoError(t, err) 90 91 t.Logf("U0 renames A.B1 -> A.B2") 92 err = RenameSubteam(context.TODO(), tcs[0].G, subteamName1, subteamName2) 93 require.NoError(t, err) 94 95 t.Logf("U1 loads A.B1 (will have stubbed link and new name)") 96 _, _, err = tcs[1].G.GetTeamLoader().Load(context.TODO(), keybase1.LoadTeamArg{ 97 ID: *subteamID, 98 ForceRepoll: true, 99 }) 100 require.NoError(t, err, "load subsubteam") 101 102 t.Logf("U0 adds U1 to A.B2.C as a writer") 103 _, err = AddMember(context.TODO(), tcs[0].G, subsubteamName2.String(), fus[1].Username, keybase1.TeamRole_WRITER, nil) 104 require.NoError(t, err) 105 106 t.Logf("U1 loads A.B2.C which will cause it to inflate the new_subteam link in A.B2") 107 _, _, err = tcs[1].G.GetTeamLoader().Load(context.TODO(), keybase1.LoadTeamArg{ 108 ID: *subsubteamID, 109 ForceRepoll: true, 110 }) 111 require.NoError(t, err, "load subsubteam") 112 } 113 114 // This was a bug that once caused the loader to get stuck. 115 // A situation where it looks like there is a subteam name 116 // collision when there is not. Because of a stubbed link. 117 // U1 is a member of R 118 // U1 gets added to R.B and caches that subteam log entry 119 // U1 gets removed from R.B 120 // A.B gets renames to R.C 121 // A new R.B gets created (different subteam ID) 122 // U1 gets added to R.B and loads. 123 // 124 // They see a name conflict and fail to load, but it's not real. 125 func TestRenameIntoMovedSubteam(t *testing.T) { 126 fus, tcs, cleanup := setupNTests(t, 2) 127 defer cleanup() 128 129 t.Logf("U0 creates R") 130 parentName, _ := createTeam2(*tcs[0]) 131 132 t.Logf("U0 adds U1 to R as a WRITER") 133 _, err := AddMember(context.TODO(), tcs[0].G, parentName.String(), fus[1].Username, keybase1.TeamRole_WRITER, nil) 134 require.NoError(t, err) 135 136 subteamNameB := createTeamName(t, parentName.String(), "bbb") 137 subteamNameC := createTeamName(t, parentName.String(), "ccc") 138 139 t.Logf("U0 creates R.B (subteam 1)") 140 subteamID1, err := CreateSubteam(context.TODO(), tcs[0].G, "bbb", parentName, keybase1.TeamRole_NONE /* addSelfAs */) 141 require.NoError(t, err) 142 _ = subteamID1 143 144 t.Logf("U0 adds U1 to R.B (1) as a WRITER") 145 _, err = AddMember(context.TODO(), tcs[0].G, subteamNameB.String(), fus[1].Username, keybase1.TeamRole_WRITER, nil) 146 require.NoError(t, err) 147 148 t.Logf("U1 loads R") 149 _, _, err = tcs[1].G.GetTeamLoader().Load(context.TODO(), keybase1.LoadTeamArg{ 150 ID: parentName.ToPrivateTeamID(), 151 ForceRepoll: true, 152 }) 153 require.NoError(t, err) 154 155 t.Logf("U0 removes U1 from R.B (1)") 156 err = RemoveMember(context.TODO(), tcs[0].G, subteamNameB.String(), fus[1].Username) 157 require.NoError(t, err) 158 159 t.Logf("U0 renames R.B (1) to R.C") 160 err = RenameSubteam(context.TODO(), tcs[0].G, subteamNameB, subteamNameC) 161 require.NoError(t, err) 162 163 t.Logf("U0 creates R.B (subteam 2) which is the SECOND R.B to be created") 164 subteamID2, err := CreateSubteam(context.TODO(), tcs[0].G, "bbb", parentName, keybase1.TeamRole_NONE /* addSelfAs */) 165 require.NoError(t, err) 166 _ = subteamID2 167 168 t.Logf("U0 adds U1 to R.B (2) as a WRITER") 169 _, err = AddMember(context.TODO(), tcs[0].G, subteamNameB.String(), fus[1].Username, keybase1.TeamRole_WRITER, nil) 170 require.NoError(t, err) 171 172 t.Logf("U1 loads R") 173 _, _, err = tcs[1].G.GetTeamLoader().Load(context.TODO(), keybase1.LoadTeamArg{ 174 ID: parentName.ToPrivateTeamID(), 175 ForceRepoll: true, 176 }) 177 require.NoError(t, err) 178 179 // TODO check the subteam list 180 } 181 182 func testHiddenRotateRename(t *testing.T, rotateParent bool, rotateChild bool) { 183 tc := SetupTest(t, "team", 1) 184 defer tc.Cleanup() 185 186 u, err := kbtest.CreateAndSignupFakeUser("t", tc.G) 187 require.NoError(t, err) 188 189 parentTeamName, err := keybase1.TeamNameFromString(u.Username + "T") 190 require.NoError(t, err) 191 parentTeamID, err := CreateRootTeam(context.TODO(), tc.G, parentTeamName.String(), keybase1.TeamSettings{}) 192 require.NoError(t, err) 193 194 subteamBasename := "bb1" 195 subteamID, err := CreateSubteam(context.TODO(), tc.G, subteamBasename, parentTeamName, keybase1.TeamRole_NONE /* addSelfAs */) 196 require.NoError(t, err) 197 subteamName, err := parentTeamName.Append(subteamBasename) 198 require.NoError(t, err) 199 desiredName, err := parentTeamName.Append("bb2") 200 require.NoError(t, err) 201 202 if rotateParent { 203 parentTeam, err := GetForTestByID(context.TODO(), tc.G, *parentTeamID) 204 require.NoError(t, err) 205 err = parentTeam.Rotate(context.TODO(), keybase1.RotationType_HIDDEN) 206 require.NoError(t, err) 207 } 208 209 if rotateChild { 210 subteam, err := GetForTestByID(context.TODO(), tc.G, *subteamID) 211 require.NoError(t, err) 212 err = subteam.Rotate(context.TODO(), keybase1.RotationType_HIDDEN) 213 require.NoError(t, err) 214 } 215 216 err = RenameSubteam(context.TODO(), tc.G, subteamName, desiredName) 217 require.NoError(t, err) 218 } 219 220 func TestHiddenRotateRenameChild(t *testing.T) { 221 testHiddenRotateRename(t, false, true) 222 } 223 func TestHiddenRotateRenameParent(t *testing.T) { 224 testHiddenRotateRename(t, true, false) 225 } 226 func TestHiddenRotateRenameParentAndChild(t *testing.T) { 227 testHiddenRotateRename(t, true, true) 228 }