renderWithState will render the file using the given nonce if the file exists as a template. If it does not, it will return an error.
(r *http.Request, filePath string, state htmlState)
| 367 | // renderWithState will render the file using the given nonce if the file exists |
| 368 | // as a template. If it does not, it will return an error. |
| 369 | func (h *Handler) renderHTMLWithState(r *http.Request, filePath string, state htmlState) ([]byte, error) { |
| 370 | af := *(h.opts.AppearanceFetcher.Load()) |
| 371 | if filePath == "" { |
| 372 | filePath = "index.html" |
| 373 | } |
| 374 | tmpl := h.htmlTemplates.Lookup(filePath) |
| 375 | if tmpl == nil { |
| 376 | return nil, xerrors.Errorf("template %q not found", filePath) |
| 377 | } |
| 378 | |
| 379 | // Cookies are sent when requesting HTML, so we can get the user |
| 380 | // and pre-populate the state for the frontend to reduce requests. |
| 381 | // We use a noop response writer because we don't want to write |
| 382 | // anything to the response and break the HTML, an error means we |
| 383 | // simply don't pre-populate the state. |
| 384 | noopRW := noopResponseWriter{} |
| 385 | apiKey, actor, ok := httpmw.ExtractAPIKey(noopRW, r, httpmw.ExtractAPIKeyConfig{ |
| 386 | Optional: true, |
| 387 | DB: h.opts.Database, |
| 388 | OAuth2Configs: h.opts.OAuth2Configs, |
| 389 | // Special case for site, we can always disable refresh here because |
| 390 | // the frontend will perform API requests if this fails. |
| 391 | DisableSessionExpiryRefresh: true, |
| 392 | RedirectToLogin: false, |
| 393 | SessionTokenFunc: nil, |
| 394 | }) |
| 395 | if !ok || apiKey == nil || actor == nil { |
| 396 | var cfg codersdk.AppearanceConfig |
| 397 | // nolint:gocritic // User is not expected to be signed in. |
| 398 | ctx := dbauthz.AsSystemRestricted(r.Context()) |
| 399 | cfg, _ = af.Fetch(ctx) |
| 400 | state.ApplicationName = html.EscapeString(applicationNameOrDefault(cfg)) |
| 401 | state.LogoURL = html.EscapeString(cfg.LogoURL) |
| 402 | return execTmpl(tmpl, state) |
| 403 | } |
| 404 | |
| 405 | ctx := dbauthz.As(r.Context(), *actor) |
| 406 | |
| 407 | var eg errgroup.Group |
| 408 | var user database.User |
| 409 | var userAppearance codersdk.UserAppearanceSettings |
| 410 | orgIDs := []uuid.UUID{} |
| 411 | var userOrgs []database.Organization |
| 412 | eg.Go(func() error { |
| 413 | var err error |
| 414 | user, err = h.opts.Database.GetUserByID(ctx, apiKey.UserID) |
| 415 | return err |
| 416 | }) |
| 417 | eg.Go(func() error { |
| 418 | settings, err := h.opts.Database.GetUserAppearanceSettings(ctx, apiKey.UserID) |
| 419 | if err != nil { |
| 420 | return err |
| 421 | } |
| 422 | userAppearance = userAppearanceSettingsFromRow(settings) |
| 423 | return nil |
| 424 | }) |
| 425 | eg.Go(func() error { |
| 426 | memberIDs, err := h.opts.Database.GetOrganizationIDsByMemberIDs(ctx, []uuid.UUID{apiKey.UserID}) |
no test coverage detected