Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ff78558

Browse files
authored
chore: don't require an organization to read starter templates (#14190)
1 parent fab1960 commit ff78558

File tree

14 files changed

+165
-28
lines changed

14 files changed

+165
-28
lines changed

coderd/apidoc/docs.go

+29
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

+25
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/coderd.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,7 @@ func New(options *Options) *API {
871871
r.Route("/templates", func(r chi.Router) {
872872
r.Post("/", api.postTemplateByOrganization)
873873
r.Get("/", api.templatesByOrganization())
874-
r.Get("/examples", api.templateExamples)
874+
r.Get("/examples", api.templateExamplesByOrganization)
875875
r.Route("/{templatename}", func(r chi.Router) {
876876
r.Get("/", api.templateByOrganizationAndName)
877877
r.Route("/versions/{templateversionname}", func(r chi.Router) {
@@ -915,6 +915,7 @@ func New(options *Options) *API {
915915
apiKeyMiddleware,
916916
)
917917
r.Get("/", api.fetchTemplates(nil))
918+
r.Get("/examples", api.templateExamples)
918919
r.Route("/{template}", func(r chi.Router) {
919920
r.Use(
920921
httpmw.ExtractTemplateParam(options.Database),

coderd/templates.go

+29-1
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,8 @@ func (api *API) templateDAUs(rw http.ResponseWriter, r *http.Request) {
821821
// @Param organization path string true "Organization ID" format(uuid)
822822
// @Success 200 {array} codersdk.TemplateExample
823823
// @Router /organizations/{organization}/templates/examples [get]
824-
func (api *API) templateExamples(rw http.ResponseWriter, r *http.Request) {
824+
// @Deprecated Use /templates/examples instead
825+
func (api *API) templateExamplesByOrganization(rw http.ResponseWriter, r *http.Request) {
825826
var (
826827
ctx = r.Context()
827828
organization = httpmw.OrganizationParam(r)
@@ -844,6 +845,33 @@ func (api *API) templateExamples(rw http.ResponseWriter, r *http.Request) {
844845
httpapi.Write(ctx, rw, http.StatusOK, ex)
845846
}
846847

848+
// @Summary Get template examples
849+
// @ID get-template-examples
850+
// @Security CoderSessionToken
851+
// @Produce json
852+
// @Tags Templates
853+
// @Success 200 {array} codersdk.TemplateExample
854+
// @Router /templates/examples [get]
855+
func (api *API) templateExamples(rw http.ResponseWriter, r *http.Request) {
856+
ctx := r.Context()
857+
858+
if !api.Authorize(r, policy.ActionRead, rbac.ResourceTemplate.AnyOrganization()) {
859+
httpapi.ResourceNotFound(rw)
860+
return
861+
}
862+
863+
ex, err := examples.List()
864+
if err != nil {
865+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
866+
Message: "Internal error fetching examples.",
867+
Detail: err.Error(),
868+
})
869+
return
870+
}
871+
872+
httpapi.Write(ctx, rw, http.StatusOK, ex)
873+
}
874+
847875
func (api *API) convertTemplates(templates []database.Template) []codersdk.Template {
848876
apiTemplates := make([]codersdk.Template, 0, len(templates))
849877

coderd/templateversions_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -1097,17 +1097,17 @@ func TestPreviousTemplateVersion(t *testing.T) {
10971097
})
10981098
}
10991099

1100-
func TestTemplateExamples(t *testing.T) {
1100+
func TestStarterTemplates(t *testing.T) {
11011101
t.Parallel()
11021102
t.Run("OK", func(t *testing.T) {
11031103
t.Parallel()
11041104
client := coderdtest.New(t, nil)
1105-
user := coderdtest.CreateFirstUser(t, client)
1105+
_ = coderdtest.CreateFirstUser(t, client)
11061106

11071107
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
11081108
defer cancel()
11091109

1110-
ex, err := client.TemplateExamples(ctx, user.OrganizationID)
1110+
ex, err := client.StarterTemplates(ctx)
11111111
require.NoError(t, err)
11121112
ls, err := examples.List()
11131113
require.NoError(t, err)

codersdk/templates.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -472,9 +472,16 @@ type AgentStatsReportResponse struct {
472472
TxBytes int64 `json:"tx_bytes"`
473473
}
474474

475-
// TemplateExamples lists example templates embedded in coder.
476-
func (c *Client) TemplateExamples(ctx context.Context, organizationID uuid.UUID) ([]TemplateExample, error) {
477-
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/templates/examples", organizationID), nil)
475+
// TemplateExamples lists example templates available in Coder.
476+
//
477+
// Deprecated: Use StarterTemplates instead.
478+
func (c *Client) TemplateExamples(ctx context.Context, _ uuid.UUID) ([]TemplateExample, error) {
479+
return c.StarterTemplates(ctx)
480+
}
481+
482+
// StarterTemplates lists example templates available in Coder.
483+
func (c *Client) StarterTemplates(ctx context.Context) ([]TemplateExample, error) {
484+
res, err := c.Request(ctx, http.MethodGet, "/api/v2/templates/examples", nil)
478485
if err != nil {
479486
return nil, err
480487
}

docs/api/templates.md

+54
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

site/src/api/api.ts

+3-7
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ class ApiMethods {
483483
};
484484

485485
deleteToken = async (keyId: string): Promise<void> => {
486-
await this.axios.delete("/api/v2/users/me/keys/" + keyId);
486+
await this.axios.delete(`/api/v2/users/me/keys/${keyId}`);
487487
};
488488

489489
createToken = async (
@@ -1754,12 +1754,8 @@ class ApiMethods {
17541754
/**
17551755
* @param organization Can be the organization's ID or name
17561756
*/
1757-
getTemplateExamples = async (
1758-
organization: string,
1759-
): Promise<TypesGen.TemplateExample[]> => {
1760-
const response = await this.axios.get(
1761-
`/api/v2/organizations/${organization}/templates/examples`,
1762-
);
1757+
getTemplateExamples = async (): Promise<TypesGen.TemplateExample[]> => {
1758+
const response = await this.axios.get(`/api/v2/templates/examples`);
17631759

17641760
return response.data;
17651761
};

site/src/api/queries/templates.ts

+3-6
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,10 @@ export const setGroupRole = (
112112
};
113113
};
114114

115-
export const templateExamples = (organizationId: string) => {
115+
export const templateExamples = () => {
116116
return {
117-
queryKey: [
118-
...getTemplatesByOrganizationQueryKey(organizationId),
119-
"examples",
120-
],
121-
queryFn: () => API.getTemplateExamples(organizationId),
117+
queryKey: ["templates", "examples"],
118+
queryFn: () => API.getTemplateExamples(),
122119
};
123120
};
124121

site/src/pages/CreateTemplatePage/ImportStarterTemplateView.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export const ImportStarterTemplateView: FC<CreateTemplatePageViewProps> = ({
3131
const { multiple_organizations: organizationsEnabled } =
3232
useFeatureVisibility();
3333
const [searchParams] = useSearchParams();
34-
const templateExamplesQuery = useQuery(templateExamples("default"));
34+
const templateExamplesQuery = useQuery(templateExamples());
3535
const templateExample = templateExamplesQuery.data?.find(
3636
(e) => e.id === searchParams.get("exampleId")!,
3737
);

site/src/pages/CreateTemplatesGalleryPage/CreateTemplatesGalleryPage.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { StarterTemplatesPageView } from "./StarterTemplatesPageView";
1111

1212
const CreateTemplatesGalleryPage: FC = () => {
1313
const { experiments } = useDashboard();
14-
const templateExamplesQuery = useQuery(templateExamples("default"));
14+
const templateExamplesQuery = useQuery(templateExamples());
1515
const starterTemplatesByTag = templateExamplesQuery.data
1616
? // Currently, the scratch template should not be displayed on the starter templates page.
1717
getTemplatesByTag(removeScratchExample(templateExamplesQuery.data))

site/src/pages/StarterTemplatePage/StarterTemplatePage.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { StarterTemplatePageView } from "./StarterTemplatePageView";
88

99
const StarterTemplatePage: FC = () => {
1010
const { exampleId } = useParams() as { exampleId: string };
11-
const templateExamplesQuery = useQuery(templateExamples("default"));
11+
const templateExamplesQuery = useQuery(templateExamples());
1212
const starterTemplate = templateExamplesQuery.data?.find(
1313
(example) => example.id === exampleId,
1414
);

site/src/pages/TemplatesPage/TemplatesPage.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const TemplatesPage: FC = () => {
1111

1212
const templatesQuery = useQuery(templates());
1313
const examplesQuery = useQuery({
14-
...templateExamples("default"),
14+
...templateExamples(),
1515
enabled: permissions.createTemplates,
1616
});
1717
const error = templatesQuery.error || examplesQuery.error;

site/src/testHelpers/handlers.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,6 @@ export const handlers = [
4747
http.get("/api/v2/organizations/:organizationId", () => {
4848
return HttpResponse.json(M.MockOrganization);
4949
}),
50-
http.get("/api/v2/organizations/:organizationId/templates/examples", () => {
51-
return HttpResponse.json([M.MockTemplateExample, M.MockTemplateExample2]);
52-
}),
5350
http.get(
5451
"/api/v2/organizations/:organizationId/templates/:templateId",
5552
() => {
@@ -81,6 +78,9 @@ export const handlers = [
8178
),
8279

8380
// templates
81+
http.get("/api/v2/templates/examples", () => {
82+
return HttpResponse.json([M.MockTemplateExample, M.MockTemplateExample2]);
83+
}),
8484
http.get("/api/v2/templates/:templateId", () => {
8585
return HttpResponse.json(M.MockTemplate);
8686
}),

0 commit comments

Comments
 (0)