@@ -9,13 +9,11 @@ import (
99"github.com/google/uuid"
1010"golang.org/x/xerrors"
1111
12- "github.com/coder/coder/v2/coderd"
1312"github.com/coder/coder/v2/coderd/audit"
1413"github.com/coder/coder/v2/coderd/database"
1514"github.com/coder/coder/v2/coderd/database/db2sdk"
1615"github.com/coder/coder/v2/coderd/httpapi"
1716"github.com/coder/coder/v2/coderd/httpmw"
18- "github.com/coder/coder/v2/coderd/rbac/policy"
1917"github.com/coder/coder/v2/codersdk"
2018)
2119
@@ -394,30 +392,60 @@ func (api *API) group(rw http.ResponseWriter, r *http.Request) {
394392// @Success 200 {array} codersdk.Group
395393// @Router /organizations/{organization}/groups [get]
396394func (api * API )groupsByOrganization (rw http.ResponseWriter ,r * http.Request ) {
395+ var (
396+ org = httpmw .OrganizationParam (r )
397+ )
398+ values := r .URL .Query ()
399+ values .Set ("organization" ,org .ID .String ())
400+ r .URL .RawQuery = values .Encode ()
401+
397402api .groups (rw ,r )
398403}
399404
405+ // @Summary Get groups
406+ // @ID get-groups
407+ // @Security CoderSessionToken
408+ // @Produce json
409+ // @Tags Enterprise
410+ // @Param organization query string true "Organization ID or name"
411+ // @Param has_member query string true "User ID or name"
412+ // @Success 200 {array} codersdk.Group
413+ // @Router /groups [get]
400414func (api * API )groups (rw http.ResponseWriter ,r * http.Request ) {
401415var (
402416ctx = r .Context ()
403- org = httpmw .OrganizationParam (r )
404417)
405418
406- groups ,err := api .Database .GetGroups (ctx , database.GetGroupsParams {
407- OrganizationID :org .ID ,
419+ var filter database.GetGroupsParams
420+ parser := httpapi .NewQueryParamParser ()
421+ // Organization selector can be an org ID or name
422+ filter .OrganizationID = parser .UUIDorName (r .URL .Query (),uuid .Nil ,"has_member" ,func (orgName string ) (uuid.UUID ,error ) {
423+ org ,err := api .Database .GetOrganizationByName (ctx ,orgName )
424+ if err != nil {
425+ return uuid .Nil ,xerrors .Errorf ("organization %q not found" ,orgName )
426+ }
427+ return org .ID ,nil
408428})
409- if err != nil && ! errors .Is (err ,sql .ErrNoRows ) {
410- httpapi .InternalServerError (rw ,err )
429+
430+ // has_member selector can be a user ID or username
431+ filter .HasMemberID = parser .UUIDorName (r .URL .Query (),uuid .Nil ,"has_member" ,func (username string ) (uuid.UUID ,error ) {
432+ user ,err := api .Database .GetUserByEmailOrUsername (ctx , database.GetUserByEmailOrUsernameParams {
433+ Username :username ,
434+ Email :"" ,
435+ })
436+ if err != nil {
437+ return uuid .Nil ,xerrors .Errorf ("user %q not found" ,username )
438+ }
439+ return user .ID ,nil
440+ })
441+
442+ groups ,err := api .Database .GetGroups (ctx ,filter )
443+ if httpapi .Is404Error (err ) {
444+ httpapi .ResourceNotFound (rw )
411445return
412446}
413-
414- // Filter groups based on rbac permissions
415- groups ,err = coderd .AuthorizeFilter (api .AGPL .HTTPAuth ,r ,policy .ActionRead ,groups )
416447if err != nil {
417- httpapi .Write (ctx ,rw ,http .StatusInternalServerError , codersdk.Response {
418- Message :"Internal error fetching groups." ,
419- Detail :err .Error (),
420- })
448+ httpapi .InternalServerError (rw ,err )
421449return
422450}
423451