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

     1  package systests
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/keybase/client/go/libkb"
     8  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
     9  	"github.com/keybase/client/go/teams"
    10  	"github.com/keybase/clockwork"
    11  	"github.com/stretchr/testify/require"
    12  	context "golang.org/x/net/context"
    13  )
    14  
    15  func TestTeamInviteSeitanInvitelinkHappy(t *testing.T) {
    16  	testTeamInviteSeitanInvitelinkHappy(t, false /* implicitAdmin */)
    17  	testTeamInviteSeitanInvitelinkHappy(t, true /* implicitAdmin */)
    18  }
    19  
    20  func testTeamInviteSeitanInvitelinkHappy(t *testing.T, implicitAdmin bool) {
    21  	tt := newTeamTester(t)
    22  	defer tt.cleanup()
    23  
    24  	alice := tt.addUser("kvr")
    25  	bob := tt.addUser("eci")
    26  
    27  	teamIDParent, teamNameParent := alice.createTeam2()
    28  	teamID := teamIDParent
    29  	teamName := teamNameParent
    30  	t.Logf("Created team %v %v", teamIDParent, teamNameParent)
    31  	if implicitAdmin {
    32  		subteamID, err := teams.CreateSubteam(context.TODO(), tt.users[0].tc.G, "sub1", teamNameParent, keybase1.TeamRole_NONE /* addSelfAs */)
    33  		require.NoError(t, err)
    34  		teamID = *subteamID
    35  		subteamName, err := teamNameParent.Append("sub1")
    36  		require.NoError(t, err)
    37  		teamName = subteamName
    38  		t.Logf("Created subteam %v %v", teamID, teamName)
    39  	}
    40  
    41  	maxUses, err := keybase1.NewTeamInviteFiniteUses(3)
    42  	require.NoError(t, err)
    43  	etime := keybase1.ToUnixTime(time.Now().Add(24 * time.Hour))
    44  	link, err := alice.teamsClient.TeamCreateSeitanInvitelink(context.TODO(), keybase1.TeamCreateSeitanInvitelinkArg{
    45  		Teamname: teamName.String(),
    46  		Role:     keybase1.TeamRole_WRITER,
    47  		MaxUses:  maxUses,
    48  		Etime:    &etime,
    49  	})
    50  	require.NoError(t, err)
    51  
    52  	t.Logf("Created token %v", link)
    53  
    54  	details := alice.teamGetDetails(teamName.String())
    55  	require.Len(t, details.AnnotatedActiveInvites, 1)
    56  	for _, aInvite := range details.AnnotatedActiveInvites {
    57  		invite := aInvite.InviteMetadata.Invite
    58  		require.Equal(t, keybase1.TeamRole_WRITER, invite.Role)
    59  		tic, err := invite.Type.C()
    60  		require.NoError(t, err)
    61  		require.Equal(t, keybase1.TeamInviteCategory_INVITELINK, tic)
    62  	}
    63  
    64  	bob.kickTeamRekeyd()
    65  	err = bob.teamsClient.TeamAcceptInvite(context.TODO(), keybase1.TeamAcceptInviteArg{
    66  		Token: string(link.Ikey),
    67  	})
    68  	require.NoError(t, err)
    69  
    70  	t.Logf("User used token, waiting for rekeyd")
    71  
    72  	alice.waitForTeamChangedGregor(teamID, keybase1.Seqno(3))
    73  
    74  	t0, err := teams.GetTeamByNameForTest(context.TODO(), alice.tc.G, teamName.String(), false /* public */, true /* needAdmin */)
    75  	require.NoError(t, err)
    76  
    77  	role, err := t0.MemberRole(context.TODO(), teams.NewUserVersion(bob.uid, 1))
    78  	require.NoError(t, err)
    79  	require.Equal(t, role, keybase1.TeamRole_WRITER)
    80  }
    81  
    82  func TestTeamInviteLinkAfterLeave(t *testing.T) {
    83  	tt := newTeamTester(t)
    84  	defer tt.cleanup()
    85  
    86  	alice := tt.addUser("ali")
    87  	bob := tt.addUser("bob")
    88  
    89  	teamID, teamName := alice.createTeam2()
    90  	maxUses, err := keybase1.NewTeamInviteFiniteUses(100)
    91  	require.NoError(t, err)
    92  	etime := keybase1.ToUnixTime(time.Now().AddDate(1, 0, 0))
    93  	link, err := alice.teamsClient.TeamCreateSeitanInvitelink(context.TODO(), keybase1.TeamCreateSeitanInvitelinkArg{
    94  		Teamname: teamName.String(),
    95  		Role:     keybase1.TeamRole_WRITER,
    96  		MaxUses:  maxUses,
    97  		Etime:    &etime,
    98  	})
    99  	require.NoError(t, err)
   100  
   101  	t.Logf("Created team invite link: %#v", link)
   102  
   103  	bob.kickTeamRekeyd()
   104  	err = bob.teamsClient.TeamAcceptInvite(context.TODO(), keybase1.TeamAcceptInviteArg{
   105  		Token: string(link.Ikey),
   106  	})
   107  	require.NoError(t, err)
   108  
   109  	alice.waitForTeamChangedGregor(teamID, keybase1.Seqno(3))
   110  
   111  	// Bob leaves.
   112  	bob.leave(teamName.String())
   113  
   114  	// Make sure Bob gets different akey when accepting again, and that Alice
   115  	// doesn't hit the "invite link was accepted before last change membership"
   116  	// when handling seitan.
   117  	clock := clockwork.NewFakeClockAt(time.Now())
   118  	clock.Advance(1 * time.Second)
   119  	bob.tc.G.SetClock(clock)
   120  	alice.tc.G.SetClock(clock)
   121  
   122  	// Bob accepts the same invite again.
   123  	err = bob.teamsClient.TeamAcceptInvite(context.TODO(), keybase1.TeamAcceptInviteArg{
   124  		Token: string(link.Ikey),
   125  	})
   126  	require.NoError(t, err)
   127  
   128  	alice.waitForTeamChangedGregor(teamID, keybase1.Seqno(5))
   129  
   130  	t.Logf("removing bob; expecting to ban since he was added by invitelink most recently")
   131  	alice.removeTeamMember(teamName.String(), bob.username)
   132  	t.Logf("bob tries to rejoin")
   133  	clock.Advance(1 * time.Second)
   134  	err = bob.teamsClient.TeamAcceptInvite(context.TODO(), keybase1.TeamAcceptInviteArg{
   135  		Token: string(link.Ikey),
   136  	})
   137  	require.Error(t, err, "server won't let bob back in")
   138  	appErr, ok := err.(libkb.AppStatusError)
   139  	require.True(t, ok, "got an app err")
   140  	require.Equal(t, appErr.Code, libkb.SCTeamBanned)
   141  
   142  	t.Logf("alice adds/removes manually to clear ban")
   143  	alice.addTeamMember(teamName.String(), bob.username, keybase1.TeamRole_WRITER)
   144  	alice.removeTeamMember(teamName.String(), bob.username)
   145  
   146  	clock.Advance(1 * time.Second)
   147  	err = bob.teamsClient.TeamAcceptInvite(context.TODO(), keybase1.TeamAcceptInviteArg{
   148  		Token: string(link.Ikey),
   149  	})
   150  	require.NoError(t, err, "bob can rejoin")
   151  	alice.waitForTeamChangedGregor(teamID, keybase1.Seqno(9))
   152  	t0, err := teams.GetTeamByNameForTest(context.TODO(), alice.tc.G,
   153  		teamName.String(), false /* public */, true /* needAdmin */)
   154  	require.NoError(t, err)
   155  	role, err := t0.MemberRole(context.TODO(), teams.NewUserVersion(bob.uid, 1))
   156  	require.NoError(t, err)
   157  	require.Equal(t, role, keybase1.TeamRole_WRITER)
   158  }
   159  
   160  func TestCreateSeitanInvitelinkWithDuration(t *testing.T) {
   161  	// Test for the GUI RPC.
   162  
   163  	tt := newTeamTester(t)
   164  	defer tt.cleanup()
   165  
   166  	alice := tt.addUser("ali")
   167  	_, teamName := alice.createTeam2()
   168  
   169  	now := alice.tc.G.Clock().Now()
   170  
   171  	maxUses := keybase1.TeamMaxUsesInfinite
   172  	expireAfter := "10 Y"
   173  	_, err := alice.teamsClient.TeamCreateSeitanInvitelinkWithDuration(
   174  		context.TODO(),
   175  		keybase1.TeamCreateSeitanInvitelinkWithDurationArg{
   176  			Teamname:    teamName.String(),
   177  			Role:        keybase1.TeamRole_WRITER,
   178  			MaxUses:     maxUses,
   179  			ExpireAfter: &expireAfter,
   180  		})
   181  	require.NoError(t, err)
   182  
   183  	details := alice.teamGetDetails(teamName.String())
   184  	require.Len(t, details.AnnotatedActiveInvites, 1)
   185  	for _, aInvite := range details.AnnotatedActiveInvites {
   186  		invite := aInvite.InviteMetadata.Invite
   187  		require.Equal(t, keybase1.TeamRole_WRITER, invite.Role)
   188  		require.NotNil(t, invite.MaxUses)
   189  		require.Equal(t, keybase1.TeamMaxUsesInfinite, *invite.MaxUses)
   190  		require.NotNil(t, invite.Etime)
   191  		require.Equal(t, now.Year()+10, invite.Etime.Time().Year())
   192  		require.Equal(t, keybase1.TeamMaxUsesInfinite, *invite.MaxUses)
   193  		tic, err := invite.Type.C()
   194  		require.NoError(t, err)
   195  		require.Equal(t, keybase1.TeamInviteCategory_INVITELINK, tic)
   196  	}
   197  }