Skip to content

VPR-151 feat(auth): Dynamic login screen#216

Open
rlorenzo wants to merge 2 commits into
mainfrom
feature/VPR-151-dynamic-login-screen
Open

VPR-151 feat(auth): Dynamic login screen#216
rlorenzo wants to merge 2 commits into
mainfrom
feature/VPR-151-dynamic-login-screen

Conversation

@rlorenzo
Copy link
Copy Markdown
Contributor

@rlorenzo rlorenzo commented Jun 4, 2026

Summary

Sends unauthenticated users to a new /welcome landing page instead of redirecting straight to CAS /login, and refreshes the SVM branding across the welcome page and app chrome.

Changes

Auth / routing

  • Replace the direct /login redirect with a /welcome landing page across Razor and Vue (cookie LoginPath, profile button, session timeout, generic error, RequireLogin composable)
  • Validate ReturnUrl with Url.IsLocalUrl on Login/TwoFactor to close open-redirect paths

Branding

  • Shared _ViperBrand lockup (rod-of-asclepius mark + stacked school name) replaces UCDSVMLogo on the welcome page and main layout
  • Self-host Proxima Nova (woff2) in place of Google Fonts Roboto; /fonts served with a 1-year immutable Cache-Control
  • AVIF hero/brand images with JPEG/PNG fallback; login photos recompressed (~60% smaller); AVIF hero preloaded with a type hint
  • Dev/Test environment badges in the layout toolbar; members sign-in banner on the CAHFS auth page

Cleanup

  • Drop the dead v-show="false" loading-placeholder markup duplicated in both Vue layouts (the real skeleton lives in the Razor shells)

Testing

  • Pre-commit suite passes: npm run lint, npm run test (backend + frontend), and build verification.

Deployment

Per repo flow, merge into Development to deploy to TEST for review before merging to main.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Jun 4, 2026

Bundle Report

Changes will increase total bundle size by 59.38kB (2.78%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
viper-frontend-esm 2.2MB 59.38kB (2.78%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: viper-frontend-esm

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/GenericError-*.css 1.32kB 204.7kB 0.65%
assets/GenericError-*.js 2.15kB 23.68kB 9.99% ⚠️
assets/effort-*.js 40 bytes 23.37kB 0.17%
assets/logo-*.png (New) 15.01kB 15.01kB 100.0% 🚀
assets/proximanova-*.woff2 (New) 13.92kB 13.92kB 100.0% 🚀
assets/proximanova-*.woff2 (New) 14.16kB 14.16kB 100.0% 🚀
assets/proximanova-*.woff2 (New) 14.08kB 14.08kB 100.0% 🚀
assets/proximanova-*.woff2 (New) 14.05kB 14.05kB 100.0% 🚀
assets/logo-*.avif (New) 8.39kB 8.39kB 100.0% 🚀
assets/cts-*.js -1.13kB 7.32kB -13.33%
assets/rod-*.png (New) 4.18kB 4.18kB 100.0% 🚀
assets/students-*.js 35 bytes 3.27kB 1.08%
assets/CtsHome-*.js 48 bytes 2.34kB 2.1%
assets/cahfs-*.js 40 bytes 1.68kB 2.43%
assets/RequireLogin-*.js (New) 1.65kB 1.65kB 100.0% 🚀
assets/clinicalscheduler-*.js 40 bytes 1.61kB 2.55%
assets/cms-*.js 40 bytes 1.41kB 2.91%
assets/CAHFSAuth-*.js 723 bytes 1.38kB 109.38% ⚠️
assets/computing-*.js 40 bytes 1.02kB 4.1%
assets/UCDSVMLogo-*.png (Deleted) -29.43kB 0 bytes -100.0% 🗑️

Files in assets/GenericError-*.js:

  • ./src/assets/logo-vetmed-stacked-lockup.avif → Total Size: 149 bytes

  • ./src/layouts/ViperLayout.vue → Total Size: 134 bytes

  • ./src/assets/rod-of-asclepius-white.avif → Total Size: 3.96kB

  • ./src/components/GenericError.vue → Total Size: 140 bytes

  • ./src/assets/logo-vetmed-stacked-lockup.png → Total Size: 150 bytes

  • ./src/assets/rod-of-asclepius-white.png → Total Size: 142 bytes

Files in assets/cts-*.js:

  • ./src/layouts/ViperLayoutSimple.vue → Total Size: 152 bytes

Files in assets/CtsHome-*.js:

  • ./src/CTS/pages/CtsHome.vue → Total Size: 124 bytes

Files in assets/RequireLogin-*.js:

  • ./src/composables/RequireLogin.ts → Total Size: 2.98kB

Files in assets/CAHFSAuth-*.js:

  • ./src/CAHFS/pages/CAHFSAuth.vue → Total Size: 132 bytes

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Jun 4, 2026

Codecov Report

❌ Patch coverage is 69.06475% with 43 lines in your changes missing coverage. Please review.
✅ Project coverage is 43.16%. Comparing base (ed1f48b) to head (ed4b622).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
web/Views/Home/Welcome.cshtml 0.00% 12 Missing ⚠️
web/Program.cs 0.00% 11 Missing ⚠️
web/Classes/Utilities/WelcomePageHelper.cs 88.88% 4 Missing and 2 partials ⚠️
web/Controllers/HomeController.cs 88.67% 4 Missing and 2 partials ⚠️
web/Views/Shared/_VIPERLayout.cshtml 0.00% 6 Missing ⚠️
VueApp/src/composables/RequireLogin.ts 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #216      +/-   ##
==========================================
+ Coverage   43.02%   43.16%   +0.13%     
==========================================
  Files         881      883       +2     
  Lines       51437    51571     +134     
  Branches     4812     4841      +29     
==========================================
+ Hits        22131    22259     +128     
+ Misses      28780    28779       -1     
- Partials      526      533       +7     
Flag Coverage Δ
backend 43.24% <69.85%> (+0.14%) ⬆️
frontend 41.45% <33.33%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@rlorenzo rlorenzo force-pushed the feature/VPR-151-dynamic-login-screen branch from 564a68b to e13dba7 Compare June 4, 2026 01:08
@rlorenzo
Copy link
Copy Markdown
Contributor Author

rlorenzo commented Jun 4, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 4, 2026

✅ Action performed

Full review finished.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 4, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

Introduces a new welcome landing page with server-side return-URL validation to prevent redirect loops and open redirects. Backend validates local URLs and sanitizes return parameters in login flows. Frontend Vue components and shared views redirect to the new welcome route. Adds welcome page styling, branded header assets, and font serving infrastructure.

Changes

Welcome Page and Login Flow Redesign

Layer / File(s) Summary
Return-URL validation utility and tests
web/Classes/Utilities/WelcomePageHelper.cs, test/Classes/Utilities/WelcomePageHelperTests.cs
WelcomePageHelper validates and sanitizes local URLs, maps URL segments to human-friendly labels, and includes private URL validation and title-case helpers. Theory tests verify label resolution, rejection of absolute/scheme-relative/non-local URLs, and query/fragment stripping.
HomeController welcome/login logic and return-URL validation
web/Controllers/HomeController.cs, test/Controllers/HomeControllerTests.cs
Index serves unauthenticated users the welcome view. New Welcome action prevents redirect loops via IsWelcomeOrLoginPath, validates return URLs in Login and CAS flows with Url.IsLocalUrl, and redirects authenticated users to local URLs or root. Tests verify safe return-URL preservation for anonymous users, unsafe URL stripping, authenticated redirects, API rejection, and non-local URL blocking.
Program configuration for welcome redirect and font serving
web/Program.cs
CAS authentication redirects to /welcome instead of /login. Static file middleware serves fonts from wwwroot/fonts at /fonts with immutable cache headers.
Welcome page and brand Razor views
web/Views/Home/Welcome.cshtml, web/Views/Shared/_ViperBrand.cshtml
Welcome.cshtml renders the VIPER 2.0 landing page with hero image selection and return-URL encoding. _ViperBrand.cshtml partial displays responsive rod mark and school lockup with AVIF/PNG fallbacks.
Welcome page stylesheet with responsive design
web/wwwroot/css/welcome.css
Comprehensive 593-line stylesheet with self-hosted Proxima Nova fonts, UC Davis color tokens, header branding, full-bleed hero with layered darkening, editorial copy, sign-in card, and footer. Mobile query reflows hero vertically, removes overlays, adjusts typography, and converts footer to stacked layout.
Vue component login redirects to welcome endpoint
VueApp/src/CAHFS/pages/CAHFSAuth.vue, VueApp/src/CTS/pages/CtsHome.vue, VueApp/src/components/GenericError.vue, VueApp/src/composables/RequireLogin.ts
CAHFS auth imports getLoginUrl for branded login button. CTS home, GenericError, and RequireLogin composable redirect to welcome endpoint with URL-encoded return-path parameters including query strings.
Vue layout brand assets, header styling, and layout updates
VueApp/src/layouts/ViperLayout.vue, VueApp/src/layouts/ViperLayoutSimple.vue, VueApp/src/styles/base.css, web/wwwroot/css/site.css
ViperLayout imports and renders rod mark and school lockup assets via <picture> elements; updates logged-out card visibility to check !showViewWhenNotLoggedIn. ViperLayoutSimple removes environment display. Base and site stylesheets add Proxima Nova font declarations, brand mark styles with responsive hiding, Roboto header-sections override, drawer shadow fix, and nav float clearing.
Shared Razor view and layout component updates to welcome route
web/Views/Shared/_VIPERLayout.cshtml, web/Views/Shared/Components/ProfilePic/Default.cshtml, web/Views/Shared/Components/SessionTimeout/Default.cshtml
_VIPERLayout renders _ViperBrand partial, adds conditional environment badges, and changes login button target to ~/welcome. ProfilePic and SessionTimeout component views redirect to ~/welcome instead of ~/login.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • bsedwards
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 43.48% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly summarizes the main change: introducing a dynamic login screen (the /welcome landing page) with updated authentication routing.
Description check ✅ Passed The PR description is well-related to the changeset, detailing the /welcome landing page introduction, branding updates, routing changes, and test verification.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/VPR-151-dynamic-login-screen

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
VueApp/src/composables/RequireLogin.ts (1)

15-18: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the stale auth-flow comments.

These comments still describe a direct login/CAS redirect, but the implementation now sends users through /welcome. Please update them together so the next edit follows the actual flow instead of the old one.

As per coding guidelines: **/*.{cs,ts,tsx,vue}: Write comments explaining why, not what. Use sparingly for complex logic only.

Also applies to: 107-118

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@VueApp/src/composables/RequireLogin.ts` around lines 15 - 18, Replace the
stale descriptive comments that mention a direct CAS redirect with a concise
"why" comment explaining that the code validates a requested return path to
prevent open-redirects and then routes users through the centralized onboarding
entrypoint (/welcome) as a stable, canonical post-login flow; update both the
comment block above the login URL builder and the similar block later (the
comments adjacent to the buildLoginUrl / requireLogin functions) to state why
the fallback to /welcome exists and why path validation is necessary, avoiding
restating what the code does.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/Classes/Utilities/WelcomePageHelperTests.cs`:
- Around line 7-23: The test suite is missing a case for tilde-rooted URLs
(e.g., "~/Area/...") which IsLocalUrl accepts; update the
WelcomePageHelperTests.ResolveDestinationLabel_KnownAndFallbackCases theory data
to include a tilde-rooted input (for example "~/RAPS/Roles") and assert the same
expected label as the non-tilde form (e.g., "RAPS") so
WelcomePageHelper.ResolveDestinationLabel is verified to handle tilde-rooted
parsing correctly.

In `@VueApp/src/CAHFS/pages/CAHFSAuth.vue`:
- Around line 5-25: Replace the raw q-banner block in CAHFSAuth.vue with the
shared StatusBanner component: remove the <q-banner> usage and render
<StatusBanner> providing the equivalent avatar (use the avatar slot to render
the <q-icon name="login" color="primary"/>), set the title to "Members sign-in",
set the message text to "Sign in with your UC Davis account to open web reports
and section pages.", and render the sign-in action using the existing loginHref
(use a button/link slot or an action prop to create the Sign in button with
href=loginHref, color="primary", no-caps, label="Sign in"); do not change the
loginHref variable name and let StatusBanner handle the correct ARIA role
mapping (type prop only if you need a specific role).

In `@VueApp/src/CTS/pages/CtsHome.vue`:
- Around line 52-55: The redirect currently hard-codes "CTS/" and drops any
query string, so the ReturnUrl loses parameters (breaking later logic that reads
route.query.sendBackTo); change the assignment to preserve the full original
path and query by using the current full route (e.g., use route.fullPath or
window.location.pathname + window.location.search) when building the ReturnUrl
instead of the fixed "CTS/". Update the window.location.href construction that
uses import.meta.env.VITE_VIPER_HOME and encodeURIComponent to append the
preserved full path (reference: window.location.href assignment,
VITE_VIPER_HOME, encodeURIComponent, and route.query.sendBackTo).

In `@VueApp/src/styles/base.css`:
- Line 254: Replace the malformed comment string "/*Left Nav styles*/" with a
properly spaced block comment so it passes Stylelint (change to "/* Left Nav
styles */"); update the comment occurrence in the CSS (the comment containing
Left Nav styles) to include a leading and trailing space inside the /* */
tokens.

In `@web/Classes/Utilities/WelcomePageHelper.cs`:
- Around line 43-60: The helper incorrectly handles "~/..." URLs because
path.TrimStart('/') leaves a leading '~', causing segments[0] == "~" and
skipping AreaLabels; update the normalization to strip a leading '~' as well
(e.g., use path = path.TrimStart('~','/')) so
AreaLabels.TryGetValue(segments[0], out var label) works for "~/"-rooted URLs;
keep the existing fallback ToTitleCase(segments[^1]) behavior and ensure this
change is applied in the method that currently calls TrimStart('/') in
WelcomePageHelper (referencing AreaLabels and ToTitleCase).

In `@web/Views/Shared/Components/ProfilePic/Default.cshtml`:
- Line 48: The q-btn currently links to Url.Content("~/welcome") without
preserving the current location; update the href on the q-btn in Default.cshtml
to include a URL-encoded ReturnUrl query parameter (e.g. return Url-encode the
current request path/Url.Action/Request.RawUrl) so the welcome/login flow can
redirect back; specifically modify the q-btn href generation (the element using
Url.Content("~/welcome")) to append ?ReturnUrl={HttpUtility.UrlEncode(/* current
path */)} or equivalent helper so existing context is preserved after auth.

In `@web/wwwroot/css/site.css`:
- Line 185: The comment block "/*Left Nav styles*/" violates the
comment-whitespace-inside rule; update that block comment (the string /*Left Nav
styles*/ in the CSS) to include spaces like "/* Left Nav styles */" so Stylelint
no longer flags it.

In `@web/wwwroot/css/welcome.css`:
- Line 107: The .sr-only rule uses the deprecated clip property; update the
.sr-only CSS selector to add a modern fallback by adding clip-path: inset(50%)
alongside the existing clip value (keep clip as the fallback), ensuring the rule
still hides visually but remains accessible; locate the .sr-only selector in
welcome.css and insert clip-path: inset(50%) (and include any necessary vendor
prefixes if desired) while preserving the existing clip line as fallback.

---

Outside diff comments:
In `@VueApp/src/composables/RequireLogin.ts`:
- Around line 15-18: Replace the stale descriptive comments that mention a
direct CAS redirect with a concise "why" comment explaining that the code
validates a requested return path to prevent open-redirects and then routes
users through the centralized onboarding entrypoint (/welcome) as a stable,
canonical post-login flow; update both the comment block above the login URL
builder and the similar block later (the comments adjacent to the buildLoginUrl
/ requireLogin functions) to state why the fallback to /welcome exists and why
path validation is necessary, avoiding restating what the code does.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 08d96d9a-c8a2-46ce-9a92-8e0dff022f87

📥 Commits

Reviewing files that changed from the base of the PR and between ed1f48b and e13dba7.

⛔ Files ignored due to path filters (19)
  • VueApp/src/assets/UCDSVMLogo.png is excluded by !**/*.png
  • VueApp/src/assets/fonts/proxima-nova/proximanova-bold.woff2 is excluded by !**/*.woff2
  • VueApp/src/assets/fonts/proxima-nova/proximanova-extrabold.woff2 is excluded by !**/*.woff2
  • VueApp/src/assets/fonts/proxima-nova/proximanova-medium.woff2 is excluded by !**/*.woff2
  • VueApp/src/assets/fonts/proxima-nova/proximanova-regular.woff2 is excluded by !**/*.woff2
  • VueApp/src/assets/logo-vetmed-stacked-lockup.png is excluded by !**/*.png
  • VueApp/src/assets/rod-of-asclepius-white.png is excluded by !**/*.png
  • web/wwwroot/fonts/proxima-nova/proximanova-bold.woff2 is excluded by !**/*.woff2
  • web/wwwroot/fonts/proxima-nova/proximanova-extrabold.woff2 is excluded by !**/*.woff2
  • web/wwwroot/fonts/proxima-nova/proximanova-medium.woff2 is excluded by !**/*.woff2
  • web/wwwroot/fonts/proxima-nova/proximanova-regular.woff2 is excluded by !**/*.woff2
  • web/wwwroot/images/UCDSVMLogo.png is excluded by !**/*.png
  • web/wwwroot/images/login/photo-guinea-pig.jpg is excluded by !**/*.jpg
  • web/wwwroot/images/login/photo-horse-foal.jpg is excluded by !**/*.jpg
  • web/wwwroot/images/login/photo-ophthalmology.jpg is excluded by !**/*.jpg
  • web/wwwroot/images/login/photo-svm-building.jpg is excluded by !**/*.jpg
  • web/wwwroot/images/login/photo-vetmed-admin.jpg is excluded by !**/*.jpg
  • web/wwwroot/images/login/rod-of-asclepius-white.png is excluded by !**/*.png
  • web/wwwroot/images/logo-vetmed-stacked-lockup.png is excluded by !**/*.png
📒 Files selected for processing (28)
  • VueApp/src/CAHFS/pages/CAHFSAuth.vue
  • VueApp/src/CTS/pages/CtsHome.vue
  • VueApp/src/assets/logo-vetmed-stacked-lockup.avif
  • VueApp/src/assets/rod-of-asclepius-white.avif
  • VueApp/src/components/GenericError.vue
  • VueApp/src/composables/RequireLogin.ts
  • VueApp/src/layouts/ViperLayout.vue
  • VueApp/src/layouts/ViperLayoutSimple.vue
  • VueApp/src/styles/base.css
  • test/Classes/Utilities/WelcomePageHelperTests.cs
  • test/Controllers/HomeControllerTests.cs
  • web/Classes/Utilities/WelcomePageHelper.cs
  • web/Controllers/HomeController.cs
  • web/Program.cs
  • web/Views/Home/Welcome.cshtml
  • web/Views/Shared/Components/ProfilePic/Default.cshtml
  • web/Views/Shared/Components/SessionTimeout/Default.cshtml
  • web/Views/Shared/_VIPERLayout.cshtml
  • web/Views/Shared/_ViperBrand.cshtml
  • web/wwwroot/css/site.css
  • web/wwwroot/css/welcome.css
  • web/wwwroot/images/login/photo-guinea-pig.avif
  • web/wwwroot/images/login/photo-horse-foal.avif
  • web/wwwroot/images/login/photo-ophthalmology.avif
  • web/wwwroot/images/login/photo-svm-building.avif
  • web/wwwroot/images/login/photo-vetmed-admin.avif
  • web/wwwroot/images/login/rod-of-asclepius-white.avif
  • web/wwwroot/images/logo-vetmed-stacked-lockup.avif
💤 Files with no reviewable changes (1)
  • VueApp/src/layouts/ViperLayoutSimple.vue

Comment thread test/Classes/Utilities/WelcomePageHelperTests.cs
Comment thread VueApp/src/CAHFS/pages/CAHFSAuth.vue Outdated
Comment thread VueApp/src/CTS/pages/CtsHome.vue Outdated
Comment thread VueApp/src/styles/base.css
Comment thread web/Classes/Utilities/WelcomePageHelper.cs Outdated
Comment thread web/Views/Shared/Components/ProfilePic/Default.cshtml Outdated
Comment thread web/wwwroot/css/site.css
Comment thread web/wwwroot/css/welcome.css
@rlorenzo rlorenzo force-pushed the feature/VPR-151-dynamic-login-screen branch from e13dba7 to cc03e60 Compare June 4, 2026 03:16
@rlorenzo rlorenzo requested a review from Copilot June 4, 2026 06:10
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new unauthenticated “Welcome” landing page at /welcome (and uses it as the cookie auth LoginPath) to replace immediate redirects to CAS /login, while also refreshing SVM branding (new shared lockup, font change, and updated layout styling) across both Razor and Vue/Quasar surfaces.

Changes:

  • Add /welcome landing page flow (Razor + Vue) and route unauthenticated entry points to it, while tightening ReturnUrl validation to mitigate open redirects and redirect loops.
  • Refresh branding and layout chrome (shared _ViperBrand lockup, Proxima Nova self-hosting, updated header/footer styles, and environment badges).
  • Add unit tests covering the welcome flow, redirect-loop guard, and ReturnUrl protections.

Reviewed changes

Copilot reviewed 19 out of 47 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
web/wwwroot/css/welcome.css New standalone CSS for the unauthenticated welcome splash (fonts, tokens, responsive hero).
web/wwwroot/css/site.css Adds Proxima Nova + shared .viper-brand* styling and a few layout tweaks.
web/Views/Shared/Components/SessionTimeout/Default.cshtml Session-timeout login redirect now targets /welcome.
web/Views/Shared/Components/ProfilePic/Default.cshtml Profile button login link now targets /welcome with ReturnUrl.
web/Views/Shared/_VIPERLayout.cshtml Replaces legacy logo with _ViperBrand, adds env badges, updates login link to /welcome.
web/Views/Shared/_ViperBrand.cshtml New shared partial for the SVM brand lockup used by welcome + layout.
web/Views/Home/Welcome.cshtml New unauthenticated welcome page view with hero + sign-in CTA.
web/Program.cs Sets cookie LoginPath to /welcome and adds /fonts static-file mapping with cache headers.
web/Controllers/HomeController.cs Adds Welcome action + hero selection, validates ReturnUrl in login/CAS flow.
web/Classes/Utilities/WelcomePageHelper.cs New helper to derive a user-friendly destination label from ReturnUrl.
VueApp/src/styles/base.css Adds Proxima Nova + .viper-brand* styling for SPA header chrome.
VueApp/src/layouts/ViperLayoutSimple.vue Removes dead placeholder markup in the simple layout.
VueApp/src/layouts/ViperLayout.vue Adds new brand lockup markup and adjusts unauthenticated-view toggling.
VueApp/src/CTS/pages/CtsHome.vue Redirects unauthenticated users to /welcome with encoded ReturnUrl.
VueApp/src/composables/RequireLogin.ts Updates SPA login URL builder to route through /welcome.
VueApp/src/components/GenericError.vue Updates login link to /welcome with encoded ReturnUrl.
VueApp/src/CAHFS/pages/CAHFSAuth.vue Adds a “Members sign-in” card that links to the new welcome/login flow.
test/Controllers/HomeControllerTests.cs New tests for welcome/login redirect protections and loop-guard behavior.
test/Classes/Utilities/WelcomePageHelperTests.cs New tests for destination label resolution and local-URL rejection.
Comments suppressed due to low confidence (1)

VueApp/src/styles/base.css:193

  • #mainLayoutHeader is set to font-weight: 500 for Proxima Nova (and web/wwwroot/css/site.css sets .mainLayoutViper to 500), but the SPA .mainLayoutViper rule forces font-weight: normal, overriding the intended medium weight in the header text. This causes inconsistent typography between Razor and SPA chrome.
.mainLayoutViper {
    font-size: 1.6em !important;
    font-weight: normal;
    vertical-align: bottom;
    margin-left: 0.6em;
}

Comment thread web/Program.cs
Comment thread web/Controllers/HomeController.cs
@rlorenzo rlorenzo force-pushed the feature/VPR-151-dynamic-login-screen branch 2 times, most recently from 176f830 to b0e750d Compare June 4, 2026 07:15
Comment thread web/Controllers/HomeController.cs Fixed
@rlorenzo rlorenzo force-pushed the feature/VPR-151-dynamic-login-screen branch from b0e750d to 99a921f Compare June 4, 2026 07:27
@rlorenzo rlorenzo requested a review from Copilot June 4, 2026 07:35
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 47 changed files in this pull request and generated 3 comments.

Comment thread web/Controllers/HomeController.cs
Comment thread web/Controllers/HomeController.cs
Comment thread test/Controllers/HomeControllerTests.cs
- Replace direct /login redirect with /welcome landing page across
  Razor and Vue (cookie LoginPath, profile button, session timeout,
  generic error, RequireLogin composable)
- Validate ReturnUrl with Url.IsLocalUrl on Login/TwoFactor to close
  open-redirect paths
- Refresh SVM branding: shared _ViperBrand lockup (rod mark + stacked
  school name) replaces UCDSVMLogo on the welcome page and main layout;
  self-host Proxima Nova (woff2) in place of Google Fonts Roboto
- Add AVIF hero/brand images with JPEG/PNG fallback and recompress the
  login photos (~60% smaller); preload the AVIF hero with a type hint
- Serve /fonts with a year-long immutable Cache-Control header
- Add Dev/Test environment badges to the layout toolbar and a members
  sign-in banner to the CAHFS auth page
- Drop the dead v-show="false" loading-placeholder markup duplicated in
  both Vue layouts (the real skeleton lives in the Razor shells)
@rlorenzo rlorenzo force-pushed the feature/VPR-151-dynamic-login-screen branch from 99a921f to 3f36a85 Compare June 4, 2026 16:29
@rlorenzo rlorenzo requested a review from Copilot June 4, 2026 16:37
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 47 changed files in this pull request and generated no new comments.

Self-hosted fonts and the login hero photos used root-absolute
URLs (/fonts/..., /images/login/...) that resolve against the
origin root, bypassing the /2 path base on TEST/PROD and hitting
the legacy site — which returns HTML, so the fonts fail to decode
and the hero background never loads. Local dev (served at root)
masked this. Base-relative ../ URLs resolve against the stylesheet
location and work under any base.

- Also fixes the mirrored Proxima Nova block in site.css, so the
  authenticated chrome stops falling back to a system font on TEST
@rlorenzo
Copy link
Copy Markdown
Contributor Author

rlorenzo commented Jun 5, 2026

@bsedwards This has been merged into TEST and is ready for user evaluation/feedback.

@rlorenzo rlorenzo requested a review from bsedwards June 5, 2026 00:25
@bsedwards
Copy link
Copy Markdown
Collaborator

@bsedwards This has been merged into TEST and is ready for user evaluation/feedback.

I like the way this looks. Do you think it's possible for certain routes / pages to go directly to CAS? I'm thinking of:

  • https://secure-test.vetmed.ucdavis.edu/2/cts/epa - We've worked with the stakeholders to streamline the process as much as possible. Assessors walk up to a QR code and go directly to the page if logged in or directly to CAS if not. The interstitial will be negatively received.
  • The CAHFS intranet home page - There's already a Sign In button. We shouldn't have a Sign In button go to another Sign In button.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants