mirror of
https://github.com/coder/coder.git
synced 2025-07-09 11:45:56 +00:00
chore: add /groups endpoint to filter by organization
and/or member
(#14260)
* chore: merge get groups sql queries into 1 * Add endpoint for fetching groups with filters * remove 2 ways to customizing a fake authorizer
This commit is contained in:
@ -9,13 +9,11 @@ import (
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/coder/coder/v2/coderd"
|
||||
"github.com/coder/coder/v2/coderd/audit"
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/database/db2sdk"
|
||||
"github.com/coder/coder/v2/coderd/httpapi"
|
||||
"github.com/coder/coder/v2/coderd/httpmw"
|
||||
"github.com/coder/coder/v2/coderd/rbac/policy"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
)
|
||||
|
||||
@ -394,28 +392,65 @@ func (api *API) group(rw http.ResponseWriter, r *http.Request) {
|
||||
// @Success 200 {array} codersdk.Group
|
||||
// @Router /organizations/{organization}/groups [get]
|
||||
func (api *API) groupsByOrganization(rw http.ResponseWriter, r *http.Request) {
|
||||
org := httpmw.OrganizationParam(r)
|
||||
|
||||
values := r.URL.Query()
|
||||
values.Set("organization", org.ID.String())
|
||||
r.URL.RawQuery = values.Encode()
|
||||
|
||||
api.groups(rw, r)
|
||||
}
|
||||
|
||||
// @Summary Get groups
|
||||
// @ID get-groups
|
||||
// @Security CoderSessionToken
|
||||
// @Produce json
|
||||
// @Tags Enterprise
|
||||
// @Param organization query string true "Organization ID or name"
|
||||
// @Param has_member query string true "User ID or name"
|
||||
// @Success 200 {array} codersdk.Group
|
||||
// @Router /groups [get]
|
||||
func (api *API) groups(rw http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
ctx = r.Context()
|
||||
org = httpmw.OrganizationParam(r)
|
||||
)
|
||||
ctx := r.Context()
|
||||
|
||||
groups, err := api.Database.GetGroupsByOrganizationID(ctx, org.ID)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.InternalServerError(rw, err)
|
||||
var filter database.GetGroupsParams
|
||||
parser := httpapi.NewQueryParamParser()
|
||||
// Organization selector can be an org ID or name
|
||||
filter.OrganizationID = parser.UUIDorName(r.URL.Query(), uuid.Nil, "organization", func(orgName string) (uuid.UUID, error) {
|
||||
org, err := api.Database.GetOrganizationByName(ctx, orgName)
|
||||
if err != nil {
|
||||
return uuid.Nil, xerrors.Errorf("organization %q not found", orgName)
|
||||
}
|
||||
return org.ID, nil
|
||||
})
|
||||
|
||||
// has_member selector can be a user ID or username
|
||||
filter.HasMemberID = parser.UUIDorName(r.URL.Query(), uuid.Nil, "has_member", func(username string) (uuid.UUID, error) {
|
||||
user, err := api.Database.GetUserByEmailOrUsername(ctx, database.GetUserByEmailOrUsernameParams{
|
||||
Username: username,
|
||||
Email: "",
|
||||
})
|
||||
if err != nil {
|
||||
return uuid.Nil, xerrors.Errorf("user %q not found", username)
|
||||
}
|
||||
return user.ID, nil
|
||||
})
|
||||
parser.ErrorExcessParams(r.URL.Query())
|
||||
if len(parser.Errors) > 0 {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Query parameters have invalid values.",
|
||||
Validations: parser.Errors,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Filter groups based on rbac permissions
|
||||
groups, err = coderd.AuthorizeFilter(api.AGPL.HTTPAuth, r, policy.ActionRead, groups)
|
||||
groups, err := api.Database.GetGroups(ctx, filter)
|
||||
if httpapi.Is404Error(err) {
|
||||
httpapi.ResourceNotFound(rw)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error fetching groups.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
httpapi.InternalServerError(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user