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  }