@@ -441,6 +441,250 @@ func TestPostTemplateByOrganization(t *testing.T) {
441441})
442442}
443443
444+ func TestTemplates (t * testing.T ) {
445+ t .Parallel ()
446+
447+ t .Run ("ListEmpty" ,func (t * testing.T ) {
448+ t .Parallel ()
449+ client := coderdtest .New (t ,nil )
450+ _ = coderdtest .CreateFirstUser (t ,client )
451+
452+ ctx := testutil .Context (t ,testutil .WaitLong )
453+
454+ templates ,err := client .Templates (ctx , codersdk.TemplateFilter {})
455+ require .NoError (t ,err )
456+ require .NotNil (t ,templates )
457+ require .Len (t ,templates ,0 )
458+ })
459+
460+ // Should return only non-deprecated templates by default
461+ t .Run ("ListMultiple non-deprecated" ,func (t * testing.T ) {
462+ t .Parallel ()
463+
464+ owner ,db := coderdtest .NewWithDatabase (t ,& coderdtest.Options {IncludeProvisionerDaemon :false })
465+ user := coderdtest .CreateFirstUser (t ,owner )
466+ client ,tplAdmin := coderdtest .CreateAnotherUser (t ,owner ,user .OrganizationID ,rbac .RoleTemplateAdmin ())
467+ version := coderdtest .CreateTemplateVersion (t ,client ,user .OrganizationID ,nil )
468+ version2 := coderdtest .CreateTemplateVersion (t ,client ,user .OrganizationID ,nil )
469+ foo := coderdtest .CreateTemplate (t ,client ,user .OrganizationID ,version .ID ,func (request * codersdk.CreateTemplateRequest ) {
470+ request .Name = "foo"
471+ })
472+ bar := coderdtest .CreateTemplate (t ,client ,user .OrganizationID ,version2 .ID ,func (request * codersdk.CreateTemplateRequest ) {
473+ request .Name = "bar"
474+ })
475+
476+ ctx := testutil .Context (t ,testutil .WaitLong )
477+
478+ // Deprecate bar template
479+ deprecationMessage := "Some deprecated message"
480+ err := db .UpdateTemplateAccessControlByID (dbauthz .As (ctx ,coderdtest .AuthzUserSubject (tplAdmin ,user .OrganizationID )), database.UpdateTemplateAccessControlByIDParams {
481+ ID :bar .ID ,
482+ RequireActiveVersion :false ,
483+ Deprecated :deprecationMessage ,
484+ })
485+ require .NoError (t ,err )
486+
487+ updatedBar ,err := client .Template (ctx ,bar .ID )
488+ require .NoError (t ,err )
489+ require .True (t ,updatedBar .Deprecated )
490+ require .Equal (t ,deprecationMessage ,updatedBar .DeprecationMessage )
491+
492+ // Should return only the non-deprecated template (foo)
493+ templates ,err := client .Templates (ctx , codersdk.TemplateFilter {})
494+ require .NoError (t ,err )
495+ require .Len (t ,templates ,1 )
496+
497+ require .Equal (t ,foo .ID ,templates [0 ].ID )
498+ require .False (t ,templates [0 ].Deprecated )
499+ require .Empty (t ,templates [0 ].DeprecationMessage )
500+ })
501+
502+ // Should return only deprecated templates when filtering by deprecated:true
503+ t .Run ("ListMultiple deprecated:true" ,func (t * testing.T ) {
504+ t .Parallel ()
505+
506+ owner ,db := coderdtest .NewWithDatabase (t ,& coderdtest.Options {IncludeProvisionerDaemon :false })
507+ user := coderdtest .CreateFirstUser (t ,owner )
508+ client ,tplAdmin := coderdtest .CreateAnotherUser (t ,owner ,user .OrganizationID ,rbac .RoleTemplateAdmin ())
509+ version := coderdtest .CreateTemplateVersion (t ,client ,user .OrganizationID ,nil )
510+ version2 := coderdtest .CreateTemplateVersion (t ,client ,user .OrganizationID ,nil )
511+ foo := coderdtest .CreateTemplate (t ,client ,user .OrganizationID ,version .ID ,func (request * codersdk.CreateTemplateRequest ) {
512+ request .Name = "foo"
513+ })
514+ bar := coderdtest .CreateTemplate (t ,client ,user .OrganizationID ,version2 .ID ,func (request * codersdk.CreateTemplateRequest ) {
515+ request .Name = "bar"
516+ })
517+
518+ ctx := testutil .Context (t ,testutil .WaitLong )
519+
520+ // Deprecate foo and bar templates
521+ deprecationMessage := "Some deprecated message"
522+ err := db .UpdateTemplateAccessControlByID (dbauthz .As (ctx ,coderdtest .AuthzUserSubject (tplAdmin ,user .OrganizationID )), database.UpdateTemplateAccessControlByIDParams {
523+ ID :foo .ID ,
524+ RequireActiveVersion :false ,
525+ Deprecated :deprecationMessage ,
526+ })
527+ require .NoError (t ,err )
528+ err = db .UpdateTemplateAccessControlByID (dbauthz .As (ctx ,coderdtest .AuthzUserSubject (tplAdmin ,user .OrganizationID )), database.UpdateTemplateAccessControlByIDParams {
529+ ID :bar .ID ,
530+ RequireActiveVersion :false ,
531+ Deprecated :deprecationMessage ,
532+ })
533+ require .NoError (t ,err )
534+
535+ // Should have deprecation message set
536+ updatedFoo ,err := client .Template (ctx ,foo .ID )
537+ require .NoError (t ,err )
538+ require .True (t ,updatedFoo .Deprecated )
539+ require .Equal (t ,deprecationMessage ,updatedFoo .DeprecationMessage )
540+
541+ updatedBar ,err := client .Template (ctx ,bar .ID )
542+ require .NoError (t ,err )
543+ require .True (t ,updatedBar .Deprecated )
544+ require .Equal (t ,deprecationMessage ,updatedBar .DeprecationMessage )
545+
546+ // Should return only the deprecated templates (foo and bar)
547+ templates ,err := client .Templates (ctx , codersdk.TemplateFilter {
548+ SearchQuery :"deprecated:true" ,
549+ })
550+ require .NoError (t ,err )
551+ require .Len (t ,templates ,2 )
552+
553+ // Make sure all the deprecated templates are returned
554+ expectedTemplates := map [uuid.UUID ]codersdk.Template {
555+ updatedFoo .ID :updatedFoo ,
556+ updatedBar .ID :updatedBar ,
557+ }
558+ actualTemplates := map [uuid.UUID ]codersdk.Template {}
559+ for _ ,template := range templates {
560+ actualTemplates [template .ID ]= template
561+ }
562+
563+ require .Equal (t ,len (expectedTemplates ),len (actualTemplates ))
564+ for id ,expectedTemplate := range expectedTemplates {
565+ actualTemplate ,ok := actualTemplates [id ]
566+ require .True (t ,ok )
567+ require .Equal (t ,expectedTemplate .ID ,actualTemplate .ID )
568+ require .Equal (t ,true ,actualTemplate .Deprecated )
569+ require .Equal (t ,expectedTemplate .DeprecationMessage ,actualTemplate .DeprecationMessage )
570+ }
571+ })
572+
573+ // Should return only non-deprecated templates when filtering by deprecated:false
574+ t .Run ("ListMultiple deprecated:false" ,func (t * testing.T ) {
575+ t .Parallel ()
576+
577+ client := coderdtest .New (t ,nil )
578+ user := coderdtest .CreateFirstUser (t ,client )
579+ version := coderdtest .CreateTemplateVersion (t ,client ,user .OrganizationID ,nil )
580+ version2 := coderdtest .CreateTemplateVersion (t ,client ,user .OrganizationID ,nil )
581+ foo := coderdtest .CreateTemplate (t ,client ,user .OrganizationID ,version .ID ,func (request * codersdk.CreateTemplateRequest ) {
582+ request .Name = "foo"
583+ })
584+ bar := coderdtest .CreateTemplate (t ,client ,user .OrganizationID ,version2 .ID ,func (request * codersdk.CreateTemplateRequest ) {
585+ request .Name = "bar"
586+ })
587+
588+ ctx := testutil .Context (t ,testutil .WaitLong )
589+
590+ // Should return only the non-deprecated templates
591+ templates ,err := client .Templates (ctx , codersdk.TemplateFilter {
592+ SearchQuery :"deprecated:false" ,
593+ })
594+ require .NoError (t ,err )
595+ require .Len (t ,templates ,2 )
596+
597+ // Make sure all the non-deprecated templates are returned
598+ expectedTemplates := map [uuid.UUID ]codersdk.Template {
599+ foo .ID :foo ,
600+ bar .ID :bar ,
601+ }
602+ actualTemplates := map [uuid.UUID ]codersdk.Template {}
603+ for _ ,template := range templates {
604+ actualTemplates [template .ID ]= template
605+ }
606+
607+ require .Equal (t ,len (expectedTemplates ),len (actualTemplates ))
608+ for id ,expectedTemplate := range expectedTemplates {
609+ actualTemplate ,ok := actualTemplates [id ]
610+ require .True (t ,ok )
611+ require .Equal (t ,expectedTemplate .ID ,actualTemplate .ID )
612+ require .Equal (t ,false ,actualTemplate .Deprecated )
613+ require .Equal (t ,expectedTemplate .DeprecationMessage ,actualTemplate .DeprecationMessage )
614+ }
615+ })
616+
617+ // Should return a re-enabled template in the default (non-deprecated) list
618+ t .Run ("ListMultiple re-enabled template" ,func (t * testing.T ) {
619+ t .Parallel ()
620+
621+ owner ,db := coderdtest .NewWithDatabase (t ,& coderdtest.Options {IncludeProvisionerDaemon :false })
622+ user := coderdtest .CreateFirstUser (t ,owner )
623+ client ,tplAdmin := coderdtest .CreateAnotherUser (t ,owner ,user .OrganizationID ,rbac .RoleTemplateAdmin ())
624+ version := coderdtest .CreateTemplateVersion (t ,client ,user .OrganizationID ,nil )
625+ version2 := coderdtest .CreateTemplateVersion (t ,client ,user .OrganizationID ,nil )
626+ foo := coderdtest .CreateTemplate (t ,client ,user .OrganizationID ,version .ID ,func (request * codersdk.CreateTemplateRequest ) {
627+ request .Name = "foo"
628+ })
629+ bar := coderdtest .CreateTemplate (t ,client ,user .OrganizationID ,version2 .ID ,func (request * codersdk.CreateTemplateRequest ) {
630+ request .Name = "bar"
631+ })
632+
633+ ctx := testutil .Context (t ,testutil .WaitLong )
634+
635+ // Deprecate bar template
636+ deprecationMessage := "Some deprecated message"
637+ err := db .UpdateTemplateAccessControlByID (dbauthz .As (ctx ,coderdtest .AuthzUserSubject (tplAdmin ,user .OrganizationID )), database.UpdateTemplateAccessControlByIDParams {
638+ ID :bar .ID ,
639+ RequireActiveVersion :false ,
640+ Deprecated :deprecationMessage ,
641+ })
642+ require .NoError (t ,err )
643+
644+ updatedBar ,err := client .Template (ctx ,bar .ID )
645+ require .NoError (t ,err )
646+ require .True (t ,updatedBar .Deprecated )
647+ require .Equal (t ,deprecationMessage ,updatedBar .DeprecationMessage )
648+
649+ // Re-enable bar template
650+ err = db .UpdateTemplateAccessControlByID (dbauthz .As (ctx ,coderdtest .AuthzUserSubject (tplAdmin ,user .OrganizationID )), database.UpdateTemplateAccessControlByIDParams {
651+ ID :bar .ID ,
652+ RequireActiveVersion :false ,
653+ Deprecated :"" ,
654+ })
655+ require .NoError (t ,err )
656+
657+ reEnabledBar ,err := client .Template (ctx ,bar .ID )
658+ require .NoError (t ,err )
659+ require .False (t ,reEnabledBar .Deprecated )
660+ require .Empty (t ,reEnabledBar .DeprecationMessage )
661+
662+ // Should return only the non-deprecated templates (foo and bar)
663+ templates ,err := client .Templates (ctx , codersdk.TemplateFilter {})
664+ require .NoError (t ,err )
665+ require .Len (t ,templates ,2 )
666+
667+ // Make sure all the non-deprecated templates are returned
668+ expectedTemplates := map [uuid.UUID ]codersdk.Template {
669+ foo .ID :foo ,
670+ bar .ID :bar ,
671+ }
672+ actualTemplates := map [uuid.UUID ]codersdk.Template {}
673+ for _ ,template := range templates {
674+ actualTemplates [template .ID ]= template
675+ }
676+
677+ require .Equal (t ,len (expectedTemplates ),len (actualTemplates ))
678+ for id ,expectedTemplate := range expectedTemplates {
679+ actualTemplate ,ok := actualTemplates [id ]
680+ require .True (t ,ok )
681+ require .Equal (t ,expectedTemplate .ID ,actualTemplate .ID )
682+ require .Equal (t ,false ,actualTemplate .Deprecated )
683+ require .Equal (t ,expectedTemplate .DeprecationMessage ,actualTemplate .DeprecationMessage )
684+ }
685+ })
686+ }
687+
444688func TestTemplatesByOrganization (t * testing.T ) {
445689t .Parallel ()
446690t .Run ("ListEmpty" ,func (t * testing.T ) {
@@ -525,6 +769,48 @@ func TestTemplatesByOrganization(t *testing.T) {
525769require .Len (t ,templates ,1 )
526770require .Equal (t ,bar .ID ,templates [0 ].ID )
527771})
772+
773+ // Should return only non-deprecated templates by default
774+ t .Run ("ListMultiple non-deprecated" ,func (t * testing.T ) {
775+ t .Parallel ()
776+
777+ owner ,db := coderdtest .NewWithDatabase (t ,& coderdtest.Options {IncludeProvisionerDaemon :false })
778+ user := coderdtest .CreateFirstUser (t ,owner )
779+ client ,tplAdmin := coderdtest .CreateAnotherUser (t ,owner ,user .OrganizationID ,rbac .RoleTemplateAdmin ())
780+ version := coderdtest .CreateTemplateVersion (t ,client ,user .OrganizationID ,nil )
781+ version2 := coderdtest .CreateTemplateVersion (t ,client ,user .OrganizationID ,nil )
782+ foo := coderdtest .CreateTemplate (t ,client ,user .OrganizationID ,version .ID ,func (request * codersdk.CreateTemplateRequest ) {
783+ request .Name = "foo"
784+ })
785+ bar := coderdtest .CreateTemplate (t ,client ,user .OrganizationID ,version2 .ID ,func (request * codersdk.CreateTemplateRequest ) {
786+ request .Name = "bar"
787+ })
788+
789+ ctx := testutil .Context (t ,testutil .WaitLong )
790+
791+ // Deprecate bar template
792+ deprecationMessage := "Some deprecated message"
793+ err := db .UpdateTemplateAccessControlByID (dbauthz .As (ctx ,coderdtest .AuthzUserSubject (tplAdmin ,user .OrganizationID )), database.UpdateTemplateAccessControlByIDParams {
794+ ID :bar .ID ,
795+ RequireActiveVersion :false ,
796+ Deprecated :deprecationMessage ,
797+ })
798+ require .NoError (t ,err )
799+
800+ updatedBar ,err := client .Template (ctx ,bar .ID )
801+ require .NoError (t ,err )
802+ require .True (t ,updatedBar .Deprecated )
803+ require .Equal (t ,deprecationMessage ,updatedBar .DeprecationMessage )
804+
805+ // Should return only the non-deprecated template (foo)
806+ templates ,err := client .TemplatesByOrganization (ctx ,user .OrganizationID )
807+ require .NoError (t ,err )
808+ require .Len (t ,templates ,1 )
809+
810+ require .Equal (t ,foo .ID ,templates [0 ].ID )
811+ require .False (t ,templates [0 ].Deprecated )
812+ require .Empty (t ,templates [0 ].DeprecationMessage )
813+ })
528814}
529815
530816func TestTemplateByOrganizationAndName (t * testing.T ) {