Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement rejecting parties from a closed team, by updating the allowlist #11710

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- [11644](https://github.com/vegaprotocol/vega/issues/11644) - `liveOnly` flag has been added to the `AMM` API to show only active `AMMs`.
- [11519](https://github.com/vegaprotocol/vega/issues/11519) - Add fees to position API types.
- [11642](https://github.com/vegaprotocol/vega/issues/11642) - `AMMs` with empty price levels are now allowed.
- [11711](https://github.com/vegaprotocol/vega/issues/11711) - Manage closed team membership by updating the allow list.

### 🐛 Fixes

Expand Down
51 changes: 39 additions & 12 deletions core/teams/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,42 +134,61 @@ func (e *Engine) CreateTeam(ctx context.Context, referrer types.PartyID, determi
}

func (e *Engine) UpdateTeam(ctx context.Context, referrer types.PartyID, teamID types.TeamID, params *commandspb.UpdateReferralSet_Team) error {
teamsToUpdate, exists := e.teams[teamID]
teamToUpdate, exists := e.teams[teamID]
if !exists {
return ErrNoTeamMatchesID(teamID)
}

if teamsToUpdate.Referrer.PartyID != referrer {
if teamToUpdate.Referrer.PartyID != referrer {
return ErrOnlyReferrerCanUpdateTeam
}

// can't update if empty and nil as it's a mandatory field
if params.Name != nil && len(*params.Name) > 0 {
teamsToUpdate.Name = ptr.UnBox(params.Name)
teamToUpdate.Name = ptr.UnBox(params.Name)
}

// those apply change if not nil only?
// to be sure to not erase things by mistake?
if params.TeamUrl != nil {
teamsToUpdate.TeamURL = ptr.UnBox(params.TeamUrl)
teamToUpdate.TeamURL = ptr.UnBox(params.TeamUrl)
}

if params.AvatarUrl != nil {
teamsToUpdate.AvatarURL = ptr.UnBox(params.AvatarUrl)
teamToUpdate.AvatarURL = ptr.UnBox(params.AvatarUrl)
}

if params.Closed != nil {
teamsToUpdate.Closed = ptr.UnBox(params.Closed)
teamToUpdate.Closed = ptr.UnBox(params.Closed)
}

// prepare the teamSwitches based on the new allowlist
newAllowList := map[string]struct{}{}
for _, v := range params.AllowList {
newAllowList[v] = struct{}{}
}

for _, v := range teamToUpdate.Referees {
// if the referee is not part of the new allowlist,
// set it to switch teams at the end of the epoch
if _, ok := newAllowList[v.PartyID.String()]; !ok {
e.teamSwitches[v.PartyID] = teamSwitch{
fromTeam: teamID,
// keep it empty to notify the intent of removing this
// party completely from the team.
toTeam: "",
}
}
}

if len(params.AllowList) > 0 {
teamsToUpdate.AllowList = make([]types.PartyID, 0, len(params.AllowList))
teamToUpdate.AllowList = make([]types.PartyID, 0, len(params.AllowList))
for _, key := range params.AllowList {
teamsToUpdate.AllowList = append(teamsToUpdate.AllowList, types.PartyID(key))
teamToUpdate.AllowList = append(teamToUpdate.AllowList, types.PartyID(key))
}
}

e.notifyTeamUpdated(ctx, teamsToUpdate)
e.notifyTeamUpdated(ctx, teamToUpdate)

return nil
}
Expand Down Expand Up @@ -296,10 +315,18 @@ func (e *Engine) moveMembers(ctx context.Context, startEpochTime time.Time, epoc
JoinedAt: startEpochTime,
StartedAtEpoch: epoch,
}
toTeam := e.teams[move.toTeam]
toTeam.Referees = append(toTeam.Referees, membership)

e.allTeamMembers[partyID] = toTeam.ID
// if there's no to team, this is a referee which have been
// remove from an allowlist of a private team.
if move.toTeam.IsNoTeam() {
// just fully remove the party from the mapping.
delete(e.allTeamMembers, partyID)
} else {
// do as usual.
toTeam := e.teams[move.toTeam]
toTeam.Referees = append(toTeam.Referees, membership)
e.allTeamMembers[partyID] = toTeam.ID
}
e.notifyRefereeSwitchedTeam(ctx, move, membership)
}

Expand Down
51 changes: 51 additions & 0 deletions core/teams/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -708,3 +708,54 @@ func testMinEpochsRequired(t *testing.T) {
members = te.engine.GetTeamMembers(string(teamID1), 5)
assert.Len(t, members, 2)
}

func TestRemoveFromAllowListRemoveFromTheTeam(t *testing.T) {
ctx := vgtest.VegaContext(vgrand.RandomStr(5), vgtest.RandomI64())

te := newEngine(t)

require.False(t, te.engine.TeamExists(newTeamID(t)))

referrer1 := newPartyID(t)
referee1 := newPartyID(t)
teamID1 := newTeamID(t)
name := vgrand.RandomStr(5)
teamURL := "https://" + name + ".io"
avatarURL := "https://avatar." + name + ".io"

// create the team
expectTeamCreatedEvent(t, te)
team1CreationDate := time.Now()
te.timeService.EXPECT().GetTimeNow().Return(team1CreationDate).Times(1)

te.engine.OnEpoch(ctx, types.Epoch{Seq: 1, Action: vegapb.EpochAction_EPOCH_ACTION_START})

require.NoError(t, te.engine.CreateTeam(ctx, referrer1, teamID1,
createTeamWithAllowListCmd(t, name, teamURL, avatarURL, true, []string{referee1.String()})))
require.True(t, te.engine.TeamExists(teamID1))

// referee join the team
expectRefereeJoinedTeamEvent(t, te)
te.timeService.EXPECT().GetTimeNow().Return(team1CreationDate.Add(10 * time.Second)).Times(1)

require.NoError(t, te.engine.JoinTeam(ctx, referee1, joinTeamCmd(t, teamID1)))
require.True(t, te.engine.IsTeamMember(referee1))
// two members in the team
assert.Len(t, te.engine.GetTeamMembers(string(teamID1), 0), 2)

te.engine.OnEpoch(ctx, types.Epoch{Seq: 2, Action: vegapb.EpochAction_EPOCH_ACTION_START})

// referrer update the team to remove all allowlisted parties
expectTeamUpdatedEvent(t, te)
// te.timeService.EXPECT().GetTimeNow().Return(team1CreationDate.Add(20 * time.Second)).Times(1)
require.NoError(t, te.engine.UpdateTeam(ctx, referrer1, teamID1,
updateTeamCmd(t, name, teamURL, avatarURL, true, []string{})))
require.True(t, te.engine.TeamExists(teamID1))

// move to the next epoch
expectRefereeSwitchedTeamEvent(t, te)
te.engine.OnEpoch(ctx, types.Epoch{Seq: 2, Action: vegapb.EpochAction_EPOCH_ACTION_START})
require.False(t, te.engine.IsTeamMember(referee1))
// only referrer is team member now
assert.Len(t, te.engine.GetTeamMembers(string(teamID1), 0), 1)
}
12 changes: 12 additions & 0 deletions core/teams/helpers_for_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,18 @@ func createTeamCmd(t *testing.T, name, teamURL, avatarURL string) *commandspb.Cr
}
}

func createTeamWithAllowListCmd(t *testing.T, name, teamURL, avatarURL string, closed bool, allowList []string) *commandspb.CreateReferralSet_Team {
t.Helper()

return &commandspb.CreateReferralSet_Team{
Name: name,
TeamUrl: ptr.From(teamURL),
AvatarUrl: ptr.From(avatarURL),
Closed: closed,
AllowList: allowList,
}
}

func updateTeamCmd(t *testing.T, name, teamURL, avatarURL string, closed bool, allowList []string) *commandspb.UpdateReferralSet_Team {
t.Helper()

Expand Down
4 changes: 4 additions & 0 deletions core/types/team.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ const teamIDLength = 64

type TeamID string

func (t TeamID) IsNoTeam() bool {
return len(string(t)) <= 0
}

type Team struct {
ID TeamID

Expand Down
12 changes: 12 additions & 0 deletions datanode/sqlstore/teams.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,18 @@ func (t *Teams) RefereeJoinedTeam(ctx context.Context, referee *entities.TeamMem
func (t *Teams) RefereeSwitchedTeam(ctx context.Context, referee *entities.RefereeTeamSwitch) error {
defer metrics.StartSQLQuery("Teams", "RefereeSwitchedTeam")()

// in case the party was removed from the team owner from a team
if len(referee.ToTeamID) <= 0 {
_, err := t.Exec(
ctx,
"DELETE FROM team_members WHERE party_id = $1",
wwestgarth marked this conversation as resolved.
Show resolved Hide resolved
referee.PartyID,
)

return err
}

// normal path, team_members just being updated.
_, err := t.Exec(ctx,
`INSERT INTO team_members(team_id, party_id, joined_at, joined_at_epoch, vega_time) VALUES ($1, $2, $3, $4, $5)`,
referee.ToTeamID,
Expand Down
Loading