github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/teams/rename.go (about) 1 package teams 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/keybase/client/go/libkb" 8 "github.com/keybase/client/go/protocol/keybase1" 9 "github.com/keybase/client/go/teams/hidden" 10 ) 11 12 func RenameSubteam(ctx context.Context, g *libkb.GlobalContext, prevName keybase1.TeamName, newName keybase1.TeamName) error { 13 mctx := libkb.NewMetaContext(ctx, g) 14 mctx.Debug("RenameSubteam %v -> %v", prevName, newName) 15 16 if prevName.IsRootTeam() { 17 return fmt.Errorf("cannot rename root team: %s", prevName.String()) 18 } 19 if prevName.Depth() < 2 { 20 return fmt.Errorf("cannot rename team: '%v'", prevName) 21 } 22 if newName.Depth() != prevName.Depth() { 23 return fmt.Errorf("cannot change depth of team: %v (%v) -> %v (%v)", 24 prevName, prevName.Depth(), newName, newName.Depth()) 25 } 26 parentName, err := prevName.Parent() 27 if err != nil { 28 return err 29 } 30 checkParentName, err := newName.Parent() 31 if err != nil { 32 // this should never happen 33 return fmt.Errorf("error checking new name: %v", err) 34 } 35 if !checkParentName.Eq(parentName) { 36 return fmt.Errorf("cannot rename teams with different parents: %v != %v", checkParentName, parentName) 37 } 38 if prevName.Eq(newName) { 39 return fmt.Errorf("cannot rename team without changing name") 40 } 41 42 return RetryIfPossible(ctx, g, func(ctx context.Context, _ int) error { 43 mctx := libkb.NewMetaContext(ctx, g) 44 mctx.Debug("RenameSubteam load teams: parent:'%v' subteam:'%v'", 45 parentName.String(), prevName.String()) 46 parent, err := GetForTeamManagementByStringName(ctx, g, parentName.String(), true) 47 if err != nil { 48 return err 49 } 50 subteam, err := GetForTeamManagementByStringName(ctx, g, prevName.String(), false) 51 if err != nil { 52 return err 53 } 54 55 mctx.Debug("RenameSubteam load me") 56 me, err := loadMeForSignatures(ctx, g) 57 if err != nil { 58 return err 59 } 60 61 deviceSigningKey, err := g.ActiveDevice.SigningKey() 62 if err != nil { 63 return err 64 } 65 66 admin, err := parent.getAdminPermission(ctx) 67 if err != nil { 68 return err 69 } 70 71 err = parent.ForceMerkleRootUpdate(ctx) 72 if err != nil { 73 return err 74 } 75 76 var ratchetBlindingKeys hidden.RatchetBlindingKeySet 77 78 // Subteam renaming involves two links, one `rename_subteam` in the parent 79 // team's chain, and one `rename_up_pointer` in the subteam's chain. 80 81 mctx.Debug("RenameSubteam make sigs") 82 renameSubteamSig, err := generateRenameSubteamSigForParentChain( 83 mctx, me, deviceSigningKey, parent.chain(), subteam.ID, newName, admin, &ratchetBlindingKeys) 84 if err != nil { 85 return err 86 } 87 88 renameUpPointerSig, err := generateRenameUpPointerSigForSubteamChain( 89 mctx, 90 me, deviceSigningKey, chainPair{parent: parent.chain(), subteam: subteam.chain()}, newName, admin, &ratchetBlindingKeys) 91 if err != nil { 92 return err 93 } 94 95 err = precheckLinkToPost(ctx, g, *renameSubteamSig, parent.chain(), me.ToUserVersion()) 96 if err != nil { 97 return fmt.Errorf("cannot post link (precheck rename subteam): %v", err) 98 } 99 100 err = precheckLinkToPost(ctx, g, *renameUpPointerSig, subteam.chain(), me.ToUserVersion()) 101 if err != nil { 102 return fmt.Errorf("cannot post link (precheck rename up): %v", err) 103 } 104 105 payload := make(libkb.JSONPayload) 106 payload["sigs"] = []interface{}{renameSubteamSig, renameUpPointerSig} 107 err = ratchetBlindingKeys.AddToJSONPayload(payload) 108 if err != nil { 109 return err 110 } 111 112 mctx.Debug("RenameSubteam post") 113 _, err = mctx.G().API.PostJSON(mctx, libkb.APIArg{ 114 Endpoint: "sig/multi", 115 SessionType: libkb.APISessionTypeREQUIRED, 116 JSONPayload: payload, 117 }) 118 if err != nil { 119 return err 120 } 121 122 go func() { _ = mctx.G().GetTeamLoader().NotifyTeamRename(ctx, subteam.ID, newName.String()) }() 123 124 return nil 125 }) 126 } 127 128 func generateRenameSubteamSigForParentChain(m libkb.MetaContext, me libkb.UserForSignatures, signingKey libkb.GenericKey, parentTeam *TeamSigChainState, subteamID keybase1.TeamID, newSubteamName keybase1.TeamName, admin *SCTeamAdmin, rbk *hidden.RatchetBlindingKeySet) (item *libkb.SigMultiItem, err error) { 129 130 entropy, err := makeSCTeamEntropy() 131 if err != nil { 132 return nil, err 133 } 134 teamSection := SCTeamSection{ 135 Admin: admin, 136 ID: (SCTeamID)(parentTeam.GetID()), 137 Subteam: &SCSubteam{ 138 ID: (SCTeamID)(subteamID), 139 Name: (SCTeamName)(newSubteamName.String()), 140 }, 141 Entropy: entropy, 142 } 143 144 ratchet, err := parentTeam.makeHiddenRatchet(m) 145 if err != nil { 146 return nil, err 147 } 148 if ratchet != nil { 149 teamSection.Ratchets = ratchet.ToTeamSection() 150 rbk.Add(*ratchet) 151 } 152 153 sigBody, err := RenameSubteamSig(m.G(), me, signingKey, parentTeam, teamSection) 154 if err != nil { 155 return nil, err 156 } 157 sigJSON, err := sigBody.Marshal() 158 if err != nil { 159 return nil, err 160 } 161 162 prevLinkID, err := libkb.ImportLinkID(parentTeam.GetLatestLinkID()) 163 if err != nil { 164 return nil, err 165 } 166 seqType := seqTypeForTeamPublicness(parentTeam.IsPublic()) 167 v2Sig, _, _, err := libkb.MakeSigchainV2OuterSig( 168 m, 169 signingKey, 170 libkb.LinkTypeRenameSubteam, 171 parentTeam.GetLatestSeqno()+1, 172 sigJSON, 173 prevLinkID, 174 libkb.SigHasRevokes(false), 175 seqType, 176 libkb.SigIgnoreIfUnsupported(false), 177 nil, 178 ) 179 if err != nil { 180 return nil, err 181 } 182 183 item = &libkb.SigMultiItem{ 184 Sig: v2Sig, 185 SigningKID: signingKey.GetKID(), 186 Type: string(libkb.LinkTypeRenameSubteam), 187 SeqType: seqType, 188 SigInner: string(sigJSON), 189 TeamID: parentTeam.GetID(), 190 } 191 return item, nil 192 } 193 194 type chainPair struct { 195 parent *TeamSigChainState 196 subteam *TeamSigChainState 197 } 198 199 func generateRenameUpPointerSigForSubteamChain(m libkb.MetaContext, me libkb.UserForSignatures, signingKey libkb.GenericKey, teams chainPair, newSubteamName keybase1.TeamName, admin *SCTeamAdmin, rbk *hidden.RatchetBlindingKeySet) (item *libkb.SigMultiItem, err error) { 200 newSubteamNameStr := newSubteamName.String() 201 teamSection := SCTeamSection{ 202 Admin: admin, 203 ID: (SCTeamID)(teams.subteam.GetID()), 204 Name: (*SCTeamName)(&newSubteamNameStr), 205 Parent: &SCTeamParent{ 206 ID: SCTeamID(teams.parent.GetID()), 207 Seqno: teams.parent.GetLatestSeqno() + 1, // the seqno of the *new* parent link 208 SeqType: seqTypeForTeamPublicness(teams.parent.IsPublic()), 209 }, 210 } 211 ratchet, err := teams.subteam.makeHiddenRatchet(m) 212 if err != nil { 213 return nil, err 214 } 215 if ratchet != nil { 216 teamSection.Ratchets = ratchet.ToTeamSection() 217 rbk.Add(*ratchet) 218 } 219 220 sigBody, err := RenameUpPointerSig(m.G(), me, signingKey, teams.subteam, teamSection) 221 if err != nil { 222 return nil, err 223 } 224 sigJSON, err := sigBody.Marshal() 225 if err != nil { 226 return nil, err 227 } 228 229 prevLinkID, err := libkb.ImportLinkID(teams.subteam.GetLatestLinkID()) 230 if err != nil { 231 return nil, err 232 } 233 seqType := seqTypeForTeamPublicness(teams.subteam.IsPublic()) 234 v2Sig, _, _, err := libkb.MakeSigchainV2OuterSig( 235 m, 236 signingKey, 237 libkb.LinkTypeRenameUpPointer, 238 teams.subteam.GetLatestSeqno()+1, 239 sigJSON, 240 prevLinkID, 241 libkb.SigHasRevokes(false), 242 seqType, 243 libkb.SigIgnoreIfUnsupported(false), 244 nil, 245 ) 246 if err != nil { 247 return nil, err 248 } 249 250 item = &libkb.SigMultiItem{ 251 Sig: v2Sig, 252 SigningKID: signingKey.GetKID(), 253 Type: string(libkb.LinkTypeRenameUpPointer), 254 SeqType: seqType, 255 SigInner: string(sigJSON), 256 TeamID: teams.subteam.GetID(), 257 } 258 return item, nil 259 }