github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/git/put.go (about)

     1  package git
     2  
     3  import (
     4  	"context"
     5  	"encoding/base64"
     6  	"fmt"
     7  
     8  	"github.com/keybase/client/go/chat/globals"
     9  	"github.com/keybase/client/go/libkb"
    10  	"github.com/keybase/client/go/protocol/chat1"
    11  	"github.com/keybase/client/go/protocol/keybase1"
    12  	"github.com/keybase/go-codec/codec"
    13  )
    14  
    15  func PutMetadata(ctx context.Context, g *libkb.GlobalContext, arg keybase1.PutGitMetadataArg) error {
    16  	teamer := NewTeamer(g)
    17  	cryptoer := NewCrypto(g)
    18  	mctx := libkb.NewMetaContext(ctx, g)
    19  
    20  	teamIDVis, err := teamer.LookupOrCreate(ctx, arg.Folder)
    21  	if err != nil {
    22  		return err
    23  	}
    24  
    25  	// Translate the GitLocalMetadata struct into GitLocalMetadataVersioned,
    26  	// for versioned storage.
    27  	localMetadataVersioned := keybase1.NewGitLocalMetadataVersionedWithV1(
    28  		keybase1.GitLocalMetadataV1{
    29  			RepoName: arg.Metadata.RepoName})
    30  
    31  	mh := codec.MsgpackHandle{WriteExt: true}
    32  	var msgpackLocalMetadata []byte
    33  	enc := codec.NewEncoderBytes(&msgpackLocalMetadata, &mh)
    34  	err = enc.Encode(localMetadataVersioned)
    35  	if err != nil {
    36  		return fmt.Errorf("encoding git metadata:%v", err)
    37  	}
    38  	encryptedMetadata, err := cryptoer.Box(ctx, msgpackLocalMetadata, teamIDVis)
    39  	if err != nil {
    40  		return err
    41  	}
    42  	base64Ciphertext := base64.StdEncoding.EncodeToString(encryptedMetadata.E)
    43  	base64Nonce := base64.StdEncoding.EncodeToString(encryptedMetadata.N[:])
    44  
    45  	apiArg := libkb.APIArg{
    46  		Endpoint:    "kbfs/git/team/put",
    47  		SessionType: libkb.APISessionTypeREQUIRED,
    48  		Args: libkb.HTTPArgs{
    49  			"team_id":            libkb.S{Val: string(teamIDVis.TeamID)},
    50  			"repo_id":            libkb.S{Val: string(arg.RepoID)},
    51  			"encrypted_metadata": libkb.S{Val: base64Ciphertext},
    52  			"nonce":              libkb.S{Val: base64Nonce},
    53  			"key_generation":     libkb.I{Val: int(encryptedMetadata.Gen)},
    54  			"device_id":          libkb.S{Val: string(g.Env.GetDeviceID())},
    55  			"encryption_version": libkb.I{Val: encryptedMetadata.V},
    56  			"notify_team":        libkb.B{Val: arg.NotifyTeam},
    57  		},
    58  	}
    59  	_, err = mctx.G().GetAPI().Post(mctx, apiArg)
    60  
    61  	if err == nil {
    62  		err = sendChat(mctx, teamIDVis.TeamID, arg)
    63  	}
    64  
    65  	return err
    66  }
    67  
    68  func sendChat(mctx libkb.MetaContext, teamID keybase1.TeamID, arg keybase1.PutGitMetadataArg) error {
    69  	if arg.Folder.FolderType != keybase1.FolderType_TEAM {
    70  		// only send chat for team repos
    71  		return nil
    72  	}
    73  
    74  	settingsArg := keybase1.GetTeamRepoSettingsArg{
    75  		Folder: arg.Folder,
    76  		RepoID: arg.RepoID,
    77  	}
    78  	settings, err := GetTeamRepoSettings(mctx.Ctx(), mctx.G(), settingsArg)
    79  	if err != nil {
    80  		return err
    81  	}
    82  	if settings.ChatDisabled {
    83  		return nil
    84  	}
    85  	if settings.ChannelName == nil {
    86  		// this shouldn't happen, but protect it if it does:
    87  		mctx.Debug("invalid team repo settings:  chat enabled, but nil ChannelName.  using default.")
    88  		settings.ChannelName = &globals.DefaultTeamTopic
    89  	}
    90  
    91  	if mctx.G().ChatHelper == nil {
    92  		mctx.Debug("cannot send chat on git push to team channel because no ChatHelper")
    93  		return nil
    94  	}
    95  
    96  	if arg.Metadata.PushType == keybase1.GitPushType_DEFAULT && keybase1.TotalNumberOfCommits(arg.Metadata.Refs) == 0 {
    97  		mctx.Debug("default git push and no commits, not sending chat")
    98  		return nil
    99  	}
   100  
   101  	mctx.G().StartStandaloneChat()
   102  
   103  	subBody := chat1.NewMessageSystemWithGitpush(chat1.MessageSystemGitPush{
   104  		Team:             arg.Folder.Name,
   105  		Pusher:           mctx.G().Env.GetUsername().String(),
   106  		RepoID:           arg.RepoID,
   107  		RepoName:         string(arg.Metadata.RepoName),
   108  		Refs:             arg.Metadata.Refs,
   109  		PushType:         arg.Metadata.PushType,
   110  		PreviousRepoName: string(arg.Metadata.PreviousRepoName),
   111  	})
   112  	body := chat1.NewMessageBodyWithSystem(subBody)
   113  
   114  	mctx.Debug("sending git push system chat message to %s/%s", arg.Folder.Name, *settings.ChannelName)
   115  	_, err = mctx.G().ChatHelper.SendMsgByNameNonblock(mctx.Ctx(), arg.Folder.Name, settings.ChannelName,
   116  		chat1.ConversationMembersType_TEAM, keybase1.TLFIdentifyBehavior_CHAT_CLI, body,
   117  		chat1.MessageType_SYSTEM, nil)
   118  	return err
   119  }