Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit30c4b4d

Browse files
authored
chore: implement fetch all authorized templates api (#13678)
1 parent08e728b commit30c4b4d

File tree

7 files changed

+315
-54
lines changed

7 files changed

+315
-54
lines changed

‎coderd/apidoc/docs.go

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/apidoc/swagger.json

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/coderd.go

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ func New(options *Options) *API {
827827
r.Post("/templateversions",api.postTemplateVersionsByOrganization)
828828
r.Route("/templates",func(r chi.Router) {
829829
r.Post("/",api.postTemplateByOrganization)
830-
r.Get("/",api.templatesByOrganization)
830+
r.Get("/",api.templatesByOrganization())
831831
r.Get("/examples",api.templateExamples)
832832
r.Route("/{templatename}",func(r chi.Router) {
833833
r.Get("/",api.templateByOrganizationAndName)
@@ -869,20 +869,25 @@ func New(options *Options) *API {
869869
})
870870
})
871871
})
872-
r.Route("/templates/{template}",func(r chi.Router) {
872+
r.Route("/templates",func(r chi.Router) {
873873
r.Use(
874874
apiKeyMiddleware,
875-
httpmw.ExtractTemplateParam(options.Database),
876875
)
877-
r.Get("/daus",api.templateDAUs)
878-
r.Get("/",api.template)
879-
r.Delete("/",api.deleteTemplate)
880-
r.Patch("/",api.patchTemplateMeta)
881-
r.Route("/versions",func(r chi.Router) {
882-
r.Post("/archive",api.postArchiveTemplateVersions)
883-
r.Get("/",api.templateVersionsByTemplate)
884-
r.Patch("/",api.patchActiveTemplateVersion)
885-
r.Get("/{templateversionname}",api.templateVersionByName)
876+
r.Get("/",api.fetchTemplates(nil))
877+
r.Route("/{template}",func(r chi.Router) {
878+
r.Use(
879+
httpmw.ExtractTemplateParam(options.Database),
880+
)
881+
r.Get("/daus",api.templateDAUs)
882+
r.Get("/",api.template)
883+
r.Delete("/",api.deleteTemplate)
884+
r.Patch("/",api.patchTemplateMeta)
885+
r.Route("/versions",func(r chi.Router) {
886+
r.Post("/archive",api.postArchiveTemplateVersions)
887+
r.Get("/",api.templateVersionsByTemplate)
888+
r.Patch("/",api.patchActiveTemplateVersion)
889+
r.Get("/{templateversionname}",api.templateVersionByName)
890+
})
886891
})
887892
})
888893
r.Route("/templateversions/{templateversion}",func(r chi.Router) {

‎coderd/templates.go

Lines changed: 65 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -435,55 +435,78 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
435435
// @Param organization path string true "Organization ID" format(uuid)
436436
// @Success 200 {array} codersdk.Template
437437
// @Router /organizations/{organization}/templates [get]
438-
func (api*API)templatesByOrganization(rw http.ResponseWriter,r*http.Request) {
439-
ctx:=r.Context()
440-
organization:=httpmw.OrganizationParam(r)
438+
func (api*API)templatesByOrganization() http.HandlerFunc {
439+
// TODO: Should deprecate this endpoint and make it akin to /workspaces with
440+
// a filter. There isn't a need to make the organization filter argument
441+
//part of the query url.
442+
// mutate the filter to only include templates from the given organization.
443+
returnapi.fetchTemplates(func(r*http.Request,arg*database.GetTemplatesWithFilterParams) {
444+
organization:=httpmw.OrganizationParam(r)
445+
arg.OrganizationID=organization.ID
446+
})
447+
}
441448

442-
p:=httpapi.NewQueryParamParser()
443-
values:=r.URL.Query()
449+
// @Summary Get all templates
450+
// @ID get-all-templates
451+
// @Security CoderSessionToken
452+
// @Produce json
453+
// @Tags Templates
454+
// @Success 200 {array} codersdk.Template
455+
// @Router /templates [get]
456+
func (api*API)fetchTemplates(mutatefunc(r*http.Request,arg*database.GetTemplatesWithFilterParams)) http.HandlerFunc {
457+
returnfunc(rw http.ResponseWriter,r*http.Request) {
458+
ctx:=r.Context()
459+
460+
p:=httpapi.NewQueryParamParser()
461+
values:=r.URL.Query()
462+
463+
deprecated:= sql.NullBool{}
464+
ifvalues.Has("deprecated") {
465+
deprecated= sql.NullBool{
466+
Bool:p.Boolean(values,false,"deprecated"),
467+
Valid:true,
468+
}
469+
}
470+
iflen(p.Errors)>0 {
471+
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
472+
Message:"Invalid query params.",
473+
Validations:p.Errors,
474+
})
475+
return
476+
}
444477

445-
deprecated:= sql.NullBool{}
446-
ifvalues.Has("deprecated") {
447-
deprecated= sql.NullBool{
448-
Bool:p.Boolean(values,false,"deprecated"),
449-
Valid:true,
478+
prepared,err:=api.HTTPAuth.AuthorizeSQLFilter(r,policy.ActionRead,rbac.ResourceTemplate.Type)
479+
iferr!=nil {
480+
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
481+
Message:"Internal error preparing sql filter.",
482+
Detail:err.Error(),
483+
})
484+
return
450485
}
451-
}
452-
iflen(p.Errors)>0 {
453-
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
454-
Message:"Invalid query params.",
455-
Validations:p.Errors,
456-
})
457-
return
458-
}
459486

460-
prepared,err:=api.HTTPAuth.AuthorizeSQLFilter(r,policy.ActionRead,rbac.ResourceTemplate.Type)
461-
iferr!=nil {
462-
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
463-
Message:"Internal error preparing sql filter.",
464-
Detail:err.Error(),
465-
})
466-
return
467-
}
487+
args:= database.GetTemplatesWithFilterParams{
488+
Deprecated:deprecated,
489+
}
490+
ifmutate!=nil {
491+
mutate(r,&args)
492+
}
468493

469-
// Filter templates based on rbac permissions
470-
templates,err:=api.Database.GetAuthorizedTemplates(ctx, database.GetTemplatesWithFilterParams{
471-
OrganizationID:organization.ID,
472-
Deprecated:deprecated,
473-
},prepared)
474-
iferrors.Is(err,sql.ErrNoRows) {
475-
err=nil
476-
}
494+
// Filter templates based on rbac permissions
495+
templates,err:=api.Database.GetAuthorizedTemplates(ctx,args,prepared)
496+
iferrors.Is(err,sql.ErrNoRows) {
497+
err=nil
498+
}
477499

478-
iferr!=nil {
479-
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
480-
Message:"Internal error fetching templates in organization.",
481-
Detail:err.Error(),
482-
})
483-
return
484-
}
500+
iferr!=nil {
501+
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
502+
Message:"Internal error fetching templates in organization.",
503+
Detail:err.Error(),
504+
})
505+
return
506+
}
485507

486-
httpapi.Write(ctx,rw,http.StatusOK,api.convertTemplates(templates))
508+
httpapi.Write(ctx,rw,http.StatusOK,api.convertTemplates(templates))
509+
}
487510
}
488511

489512
// @Summary Get templates by organization and template name

‎coderd/templates_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,42 @@ func TestTemplatesByOrganization(t *testing.T) {
438438
templates,err:=client.TemplatesByOrganization(ctx,user.OrganizationID)
439439
require.NoError(t,err)
440440
require.Len(t,templates,2)
441+
442+
// Listing all should match
443+
templates,err=client.Templates(ctx)
444+
require.NoError(t,err)
445+
require.Len(t,templates,2)
446+
})
447+
t.Run("MultipleOrganizations",func(t*testing.T) {
448+
t.Parallel()
449+
client:=coderdtest.New(t,nil)
450+
owner:=coderdtest.CreateFirstUser(t,client)
451+
org2:=coderdtest.CreateOrganization(t,client, coderdtest.CreateOrganizationOptions{})
452+
user,_:=coderdtest.CreateAnotherUser(t,client,org2.ID)
453+
454+
// 2 templates in first organization
455+
version:=coderdtest.CreateTemplateVersion(t,client,owner.OrganizationID,nil)
456+
version2:=coderdtest.CreateTemplateVersion(t,client,owner.OrganizationID,nil)
457+
coderdtest.CreateTemplate(t,client,owner.OrganizationID,version.ID)
458+
coderdtest.CreateTemplate(t,client,owner.OrganizationID,version2.ID)
459+
460+
// 2 in the second organization
461+
version3:=coderdtest.CreateTemplateVersion(t,client,org2.ID,nil)
462+
version4:=coderdtest.CreateTemplateVersion(t,client,org2.ID,nil)
463+
coderdtest.CreateTemplate(t,client,org2.ID,version3.ID)
464+
coderdtest.CreateTemplate(t,client,org2.ID,version4.ID)
465+
466+
ctx:=testutil.Context(t,testutil.WaitLong)
467+
468+
// All 4 are viewable by the owner
469+
templates,err:=client.Templates(ctx)
470+
require.NoError(t,err)
471+
require.Len(t,templates,4)
472+
473+
// Only 2 are viewable by the org user
474+
templates,err=user.Templates(ctx)
475+
require.NoError(t,err)
476+
require.Len(t,templates,2)
441477
})
442478
}
443479

‎codersdk/organizations.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,25 @@ func (c *Client) TemplatesByOrganization(ctx context.Context, organizationID uui
362362
returntemplates,json.NewDecoder(res.Body).Decode(&templates)
363363
}
364364

365+
// Templates lists all viewable templates
366+
func (c*Client)Templates(ctx context.Context) ([]Template,error) {
367+
res,err:=c.Request(ctx,http.MethodGet,
368+
"/api/v2/templates",
369+
nil,
370+
)
371+
iferr!=nil {
372+
returnnil,xerrors.Errorf("execute request: %w",err)
373+
}
374+
deferres.Body.Close()
375+
376+
ifres.StatusCode!=http.StatusOK {
377+
returnnil,ReadBodyAsError(res)
378+
}
379+
380+
vartemplates []Template
381+
returntemplates,json.NewDecoder(res.Body).Decode(&templates)
382+
}
383+
365384
// TemplateByName finds a template inside the organization provided with a case-insensitive name.
366385
func (c*Client)TemplateByName(ctx context.Context,organizationID uuid.UUID,namestring) (Template,error) {
367386
ifname=="" {

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp