1
0

feat(teams): add public flags to teams to allow easier sharing with other teams (#2179)

Resolves #2173
Co-authored-by: Daniel Herrmann <daniel.herrmann1@gmail.com>
Reviewed-on: https://kolaente.dev/vikunja/vikunja/pulls/2179
Reviewed-by: konrad <k@knt.li>
Co-authored-by: waza-ari <daniel.herrmann@makerspace-darmstadt.de>
Co-committed-by: waza-ari <daniel.herrmann@makerspace-darmstadt.de>
This commit is contained in:
waza-ari
2024-03-10 14:04:32 +00:00
committed by konrad
parent d7fdefcead
commit ffa82556e0
22 changed files with 392 additions and 45 deletions

View File

@ -19,6 +19,7 @@ package models
import (
"time"
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/db"
"code.vikunja.io/api/pkg/events"
@ -53,6 +54,12 @@ type Team struct {
// A timestamp when this relation was last updated. You cannot change this value.
Updated time.Time `xorm:"updated" json:"updated"`
// Defines wether the team should be publicly discoverable when sharing a project
IsPublic bool `xorm:"not null default false" json:"is_public"`
// Query parameter controlling whether to include public projects or not
IncludePublic bool `xorm:"-" query:"include_public" json:"include_public"`
web.CRUDable `xorm:"-" json:"-"`
web.Rights `xorm:"-" json:"-"`
}
@ -100,6 +107,7 @@ type OIDCTeam struct {
Name string
OidcID string
Description string
IsPublic bool
}
// GetTeamByID gets a team by its ID
@ -287,11 +295,24 @@ func (t *Team) ReadAll(s *xorm.Session, a web.Auth, search string, page int, per
limit, start := getLimitFromPageIndex(page, perPage)
all := []*Team{}
query := s.Select("teams.*").
Table("teams").
Join("INNER", "team_members", "team_members.team_id = teams.id").
Where("team_members.user_id = ?", a.GetID()).
Where(db.ILIKE("teams.name", search))
// If public teams are enabled, we want to include them in the result
if config.ServiceEnablePublicTeams.GetBool() && t.IncludePublic {
query = query.Where(
builder.Or(
builder.Eq{"teams.is_public": true},
builder.Eq{"team_members.user_id": a.GetID()},
),
)
} else {
query = query.Where("team_members.user_id = ?", a.GetID())
}
if limit > 0 {
query = query.Limit(limit, start)
}
@ -398,7 +419,7 @@ func (t *Team) Update(s *xorm.Session, _ web.Auth) (err error) {
return
}
_, err = s.ID(t.ID).Update(t)
_, err = s.ID(t.ID).UseBool("is_public").Update(t)
if err != nil {
return
}

View File

@ -20,6 +20,7 @@ import (
"reflect"
"testing"
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/db"
"code.vikunja.io/api/pkg/user"
@ -49,6 +50,7 @@ func TestTeam_Create(t *testing.T) {
"id": team.ID,
"name": "Testteam293",
"description": "Lorem Ispum",
"is_public": false,
}, false)
})
t.Run("empty name", func(t *testing.T) {
@ -61,6 +63,27 @@ func TestTeam_Create(t *testing.T) {
require.Error(t, err)
assert.True(t, IsErrTeamNameCannotBeEmpty(err))
})
t.Run("public", func(t *testing.T) {
db.LoadAndAssertFixtures(t)
s := db.NewSession()
defer s.Close()
team := &Team{
Name: "Testteam293_Public",
Description: "Lorem Ispum",
IsPublic: true,
}
err := team.Create(s, doer)
require.NoError(t, err)
err = s.Commit()
require.NoError(t, err)
db.AssertExists(t, "teams", map[string]interface{}{
"id": team.ID,
"name": "Testteam293_Public",
"description": "Lorem Ispum",
"is_public": true,
}, false)
})
}
func TestTeam_ReadOne(t *testing.T) {
@ -126,6 +149,58 @@ func TestTeam_ReadAll(t *testing.T) {
assert.Len(t, ts, 1)
assert.Equal(t, int64(2), ts[0].ID)
})
t.Run("public discovery disabled", func(t *testing.T) {
s := db.NewSession()
defer s.Close()
team := &Team{}
// Default setting is having ServiceEnablePublicTeams disabled
// In this default case, fetching teams with or without public flag should return the same result
// Fetch without public flag
teams, _, _, err := team.ReadAll(s, doer, "", 1, 50)
require.NoError(t, err)
assert.Equal(t, reflect.Slice, reflect.TypeOf(teams).Kind())
ts := teams.([]*Team)
assert.Len(t, ts, 5)
// Fetch with public flag
team.IncludePublic = true
teams, _, _, err = team.ReadAll(s, doer, "", 1, 50)
require.NoError(t, err)
assert.Equal(t, reflect.Slice, reflect.TypeOf(teams).Kind())
ts = teams.([]*Team)
assert.Len(t, ts, 5)
})
t.Run("public discovery enabled", func(t *testing.T) {
s := db.NewSession()
defer s.Close()
team := &Team{}
// Enable ServiceEnablePublicTeams feature
config.ServiceEnablePublicTeams.Set(true)
// Fetch without public flag should be the same as before
team.IncludePublic = false
teams, _, _, err := team.ReadAll(s, doer, "", 1, 50)
require.NoError(t, err)
assert.Equal(t, reflect.Slice, reflect.TypeOf(teams).Kind())
ts := teams.([]*Team)
assert.Len(t, ts, 5)
// Fetch with public flag should return more teams
team.IncludePublic = true
teams, _, _, err = team.ReadAll(s, doer, "", 1, 50)
require.NoError(t, err)
assert.Equal(t, reflect.Slice, reflect.TypeOf(teams).Kind())
ts = teams.([]*Team)
assert.Len(t, ts, 7)
})
}
func TestTeam_Update(t *testing.T) {