github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/git/settings.go (about)

     1  package git
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  
     7  	"github.com/keybase/client/go/chat/globals"
     8  	"github.com/keybase/client/go/libkb"
     9  	"github.com/keybase/client/go/protocol/chat1"
    10  	"github.com/keybase/client/go/protocol/keybase1"
    11  )
    12  
    13  type settingsResponse struct {
    14  	ChatConvID   string          `json:"chat_conv_id"`
    15  	ChatDisabled bool            `json:"chat_disabled"`
    16  	Status       libkb.AppStatus `json:"status"`
    17  }
    18  
    19  func (r *settingsResponse) GetAppStatus() *libkb.AppStatus {
    20  	return &r.Status
    21  }
    22  
    23  func GetTeamRepoSettings(ctx context.Context, g *libkb.GlobalContext, arg keybase1.GetTeamRepoSettingsArg) (keybase1.GitTeamRepoSettings, error) {
    24  	mctx := libkb.NewMetaContext(ctx, g)
    25  	if arg.Folder.FolderType != keybase1.FolderType_TEAM {
    26  		return keybase1.GitTeamRepoSettings{ChatDisabled: true}, nil
    27  	}
    28  
    29  	apiArg, teamID, err := settingsArg(ctx, g, arg.Folder, arg.RepoID)
    30  	if err != nil {
    31  		return keybase1.GitTeamRepoSettings{}, err
    32  	}
    33  
    34  	var resp settingsResponse
    35  	if err := g.GetAPI().GetDecode(mctx, *apiArg, &resp); err != nil {
    36  		return keybase1.GitTeamRepoSettings{}, err
    37  	}
    38  
    39  	return convertTeamRepoSettings(ctx, g, teamID, resp.ChatConvID, resp.ChatDisabled)
    40  }
    41  
    42  func convertTeamRepoSettings(ctx context.Context, g *libkb.GlobalContext,
    43  	teamID keybase1.TeamID, chatConvID string, chatDisabled bool) (keybase1.GitTeamRepoSettings, error) {
    44  	settings := keybase1.GitTeamRepoSettings{
    45  		ChatDisabled: chatDisabled,
    46  	}
    47  
    48  	if !settings.ChatDisabled {
    49  		if chatConvID == "" {
    50  			// chat enabled, so use default team topic (#general)
    51  			settings.ChannelName = &globals.DefaultTeamTopic
    52  		} else {
    53  			// lookup the channel name
    54  			convID, err := chat1.MakeConvID(chatConvID)
    55  			if err != nil {
    56  				return keybase1.GitTeamRepoSettings{}, err
    57  			}
    58  			channelName, err := g.ChatHelper.GetChannelTopicName(ctx, teamID,
    59  				chat1.TopicType_CHAT, convID)
    60  			if err != nil {
    61  				// This error is non-fatal, show that chat is disabled and let
    62  				// the user chose something else.
    63  				settings.ChatDisabled = true
    64  				settings.ChannelName = nil
    65  				g.Log.CDebugf(ctx, "unable to get channel name: %v", err)
    66  			} else {
    67  				settings.ChannelName = &channelName
    68  			}
    69  		}
    70  	}
    71  
    72  	return settings, nil
    73  
    74  }
    75  
    76  func SetTeamRepoSettings(ctx context.Context, g *libkb.GlobalContext, arg keybase1.SetTeamRepoSettingsArg) error {
    77  	mctx := libkb.NewMetaContext(ctx, g)
    78  	if arg.Folder.FolderType != keybase1.FolderType_TEAM {
    79  		return errors.New("SetTeamRepoSettings denied: this repo is not a team repo")
    80  	}
    81  	apiArg, _, err := settingsArg(ctx, g, arg.Folder, arg.RepoID)
    82  	if err != nil {
    83  		return err
    84  	}
    85  	apiArg.Args["chat_disabled"] = libkb.B{Val: arg.ChatDisabled}
    86  
    87  	if arg.ChannelName != nil && *(arg.ChannelName) != "" {
    88  		// lookup the conv id for the channel name
    89  		vis := keybase1.TLFVisibility_PRIVATE
    90  		if arg.Folder.FolderType == keybase1.FolderType_PUBLIC {
    91  			vis = keybase1.TLFVisibility_PUBLIC
    92  		}
    93  		convs, err := g.ChatHelper.FindConversations(ctx, arg.Folder.Name, arg.ChannelName,
    94  			chat1.TopicType_CHAT, chat1.ConversationMembersType_TEAM, vis)
    95  		if err != nil {
    96  			return err
    97  		}
    98  		if len(convs) == 0 {
    99  			return errors.New("no channel found")
   100  		}
   101  		if len(convs) > 1 {
   102  			return errors.New("multiple channels found")
   103  		}
   104  		convID := convs[0].Info.Id
   105  		apiArg.Args["chat_conv_id"] = libkb.HexArg(convID)
   106  		apiArg.AppStatusCodes = []int{libkb.SCOk, libkb.SCTeamWritePermDenied}
   107  	}
   108  
   109  	apiRes, err := g.GetAPI().Post(mctx, *apiArg)
   110  	if err != nil {
   111  		return err
   112  	}
   113  	if apiRes.AppStatus.Code == libkb.SCTeamWritePermDenied {
   114  		return libkb.TeamWritePermDeniedError{}
   115  	}
   116  	return nil
   117  }
   118  
   119  func settingsArg(ctx context.Context, g *libkb.GlobalContext,
   120  	folder keybase1.FolderHandle, repoID keybase1.RepoID) (apiArg *libkb.APIArg, teamID keybase1.TeamID, err error) {
   121  	teamer := NewTeamer(g)
   122  	teamIDVis, err := teamer.LookupOrCreate(ctx, folder)
   123  	if err != nil {
   124  		return nil, teamID, err
   125  	}
   126  	apiArg = &libkb.APIArg{
   127  		Endpoint:    "kbfs/git/team/settings",
   128  		SessionType: libkb.APISessionTypeREQUIRED,
   129  		Args: libkb.HTTPArgs{
   130  			"team_id": libkb.S{Val: string(teamIDVis.TeamID)},
   131  			"repo_id": libkb.S{Val: string(repoID)},
   132  		},
   133  	}
   134  	return apiArg, teamIDVis.TeamID, nil
   135  }