mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
feat: Single query for all workspaces with optional filter (#1537)
* feat: Add single query for all workspaces using a filter
This commit is contained in:
@ -70,7 +70,7 @@ func (api *api) workspace(rw http.ResponseWriter, r *http.Request) {
|
||||
func (api *api) workspacesByOrganization(rw http.ResponseWriter, r *http.Request) {
|
||||
organization := httpmw.OrganizationParam(r)
|
||||
roles := httpmw.UserRoles(r)
|
||||
workspaces, err := api.Database.GetWorkspacesByOrganizationID(r.Context(), database.GetWorkspacesByOrganizationIDParams{
|
||||
workspaces, err := api.Database.GetWorkspacesWithFilter(r.Context(), database.GetWorkspacesWithFilterParams{
|
||||
OrganizationID: organization.ID,
|
||||
Deleted: false,
|
||||
})
|
||||
@ -104,30 +104,67 @@ func (api *api) workspacesByOrganization(rw http.ResponseWriter, r *http.Request
|
||||
httpapi.Write(rw, http.StatusOK, apiWorkspaces)
|
||||
}
|
||||
|
||||
func (api *api) workspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
user := httpmw.UserParam(r)
|
||||
// workspaces returns all workspaces a user can read.
|
||||
// Optional filters with query params
|
||||
func (api *api) workspaces(rw http.ResponseWriter, r *http.Request) {
|
||||
roles := httpmw.UserRoles(r)
|
||||
apiKey := httpmw.APIKey(r)
|
||||
|
||||
allWorkspaces := make([]database.Workspace, 0)
|
||||
userWorkspaces, err := api.Database.GetWorkspacesByOwnerID(r.Context(), database.GetWorkspacesByOwnerIDParams{
|
||||
OwnerID: user.ID,
|
||||
})
|
||||
// Empty strings mean no filter
|
||||
orgFilter := r.URL.Query().Get("organization_id")
|
||||
ownerFilter := r.URL.Query().Get("owner_id")
|
||||
|
||||
filter := database.GetWorkspacesWithFilterParams{Deleted: false}
|
||||
if orgFilter != "" {
|
||||
orgID, err := uuid.Parse(orgFilter)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
Message: fmt.Sprintf("organization_id must be a uuid: %s", err.Error()),
|
||||
})
|
||||
return
|
||||
}
|
||||
filter.OrganizationID = orgID
|
||||
}
|
||||
if ownerFilter == "me" {
|
||||
filter.OwnerID = apiKey.UserID
|
||||
} else if ownerFilter != "" {
|
||||
userID, err := uuid.Parse(ownerFilter)
|
||||
if err != nil {
|
||||
// Maybe it's a username
|
||||
user, err := api.Database.GetUserByEmailOrUsername(r.Context(), database.GetUserByEmailOrUsernameParams{
|
||||
// Why not just accept 1 arg and use it for both in the sql?
|
||||
Username: ownerFilter,
|
||||
Email: ownerFilter,
|
||||
})
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
Message: "owner must be a uuid or username",
|
||||
})
|
||||
return
|
||||
}
|
||||
userID = user.ID
|
||||
}
|
||||
filter.OwnerID = userID
|
||||
}
|
||||
|
||||
allowedWorkspaces := make([]database.Workspace, 0)
|
||||
allWorkspaces, err := api.Database.GetWorkspacesWithFilter(r.Context(), filter)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get workspaces for user: %s", err),
|
||||
})
|
||||
return
|
||||
}
|
||||
for _, ws := range userWorkspaces {
|
||||
for _, ws := range allWorkspaces {
|
||||
ws := ws
|
||||
err = api.Authorizer.ByRoleName(r.Context(), user.ID.String(), roles.Roles, rbac.ActionRead,
|
||||
err = api.Authorizer.ByRoleName(r.Context(), roles.ID.String(), roles.Roles, rbac.ActionRead,
|
||||
rbac.ResourceWorkspace.InOrg(ws.OrganizationID).WithOwner(ws.OwnerID.String()).WithID(ws.ID.String()))
|
||||
if err == nil {
|
||||
allWorkspaces = append(allWorkspaces, ws)
|
||||
allowedWorkspaces = append(allowedWorkspaces, ws)
|
||||
}
|
||||
}
|
||||
|
||||
apiWorkspaces, err := convertWorkspaces(r.Context(), api.Database, allWorkspaces)
|
||||
apiWorkspaces, err := convertWorkspaces(r.Context(), api.Database, allowedWorkspaces)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("convert workspaces: %s", err),
|
||||
@ -140,8 +177,9 @@ func (api *api) workspacesByUser(rw http.ResponseWriter, r *http.Request) {
|
||||
func (api *api) workspacesByOwner(rw http.ResponseWriter, r *http.Request) {
|
||||
owner := httpmw.UserParam(r)
|
||||
roles := httpmw.UserRoles(r)
|
||||
workspaces, err := api.Database.GetWorkspacesByOwnerID(r.Context(), database.GetWorkspacesByOwnerIDParams{
|
||||
workspaces, err := api.Database.GetWorkspacesWithFilter(r.Context(), database.GetWorkspacesWithFilterParams{
|
||||
OwnerID: owner.ID,
|
||||
Deleted: false,
|
||||
})
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
err = nil
|
||||
|
Reference in New Issue
Block a user