Skip to content

Show password login#94

Merged
gkostin1966 merged 11 commits intoumichfrom
show-password-login
Apr 29, 2026
Merged

Show password login#94
gkostin1966 merged 11 commits intoumichfrom
show-password-login

Conversation

@gkostin1966
Copy link
Copy Markdown
Collaborator

DEEPBLUE-466 — Config-driven password login toggle for demo environment

Summary

Restores the password login form on the demo environment without changing
production or workshop behaviour.

A new showPasswordLogin config flag (default false) acts as an exclusive toggle:

showPasswordLogin Login UI Environment
false (default) OIDC button only production, workshop — no change
true Password form only demo

Background

Deep Blue Documents has three Kubernetes environments: production, workshop, and demo.

Demo uses a two-layer auth model:

  1. oauth2-proxy gate requires U-M WebLogin (Shibboleth OIDC) — restricts access to U-M people.
  2. Inside the gate, users log in to DSpace with username/password to switch test personas.

DSpace's internal OIDC is intentionally disabled for demo so testers aren't auto-logged-in
as their own umich.edu identity. An existing UM customisation (*ngIf="authMethod.authMethodType !== 'password'") removed the password form from the UI — which was fine when OIDC was the
active method but leaves a completely blank login page now that OIDC is disabled.


Changes

src/config/auth-config.interfaces.ts

Added showPasswordLogin?: boolean to AuthConfig.

src/config/default-app-config.ts

Defaulted showPasswordLogin: false — all environments preserve current behaviour
unless they explicitly opt in.

src/app/shared/log-in/log-in.component.ts

Injected APP_CONFIG; reads flag into public showPasswordLogin: boolean.

src/app/shared/log-in/log-in.component.html

Replaced:

*ngIf="authMethod.authMethodType !== 'password'"

with the exclusive toggle:

*ngIf="showPasswordLogin === (authMethod.authMethodType === 'password')"

src/app/shared/log-in/log-in.component.spec.ts

Provided APP_CONFIG token in TestBed; updated toBe(2)toBe(1).

config/config.example.yml

Documented the new flag (commented out) in the auth: block for operators.


Configuration

Enable for demo via frontend Kubernetes ConfigMap environment variable:

DSPACE_AUTH_SHOWPASSWORDLOGIN=true

The DSpace Angular config system translates this to a proper boolean true
via getBooleanFromString (verified). Production and workshop must NOT set
this variable — omitting it is sufficient.

⚠️ This PR does not touch the Kubernetes config. Setting the env-var
in mlibrary/deepblue-documents-kube is a separate follow-up step.


Also fixed in this PR

The umich base branch had 14 TypeScript compilation errors in 9 spec files
that prevented the test suite from starting at all. Fixed as part of this PR:

  • environment.test.ts — missing serverLocation property required by BuildConfig
  • item-withdraw.component.spec.ts / item-reinstate.component.spec.tssetWithDrawn now requires a reason argument (TS2554)
  • 6 bitstream-format spec files — BitstreamFormatSupportLevel enum values renamed: Unknown → AS_IS_UNKNOWN, Known → AS_IS_KNOWN, Supported → HIGHEST_LEVEL

Testing

  • ✅ Unit tests: log-in.component.spec.ts — 2 specs, 0 failures
  • ✅ Config flow verified end-to-end: env-var → buildAppConfigextendEnvironmentWithAppConfigAPP_CONFIG token → component → template
  • isNotEmpty(false) === true confirmed — the env-var is not silently ignored when the default value is false

See PLAN_DSPACE_ANGULAR_PASSWORD_LOGIN.md for full rationale, config system
deep-dive, on-host debugging commands, and post-deployment verification steps.


Verification after demo deployment

  1. Navigate to https://demo.deepblue-documents.lib.umich.edu — gate challenges for U-M WebLogin.
  2. After passing the gate, click Log In.
  3. A username/password form appears (no OIDC button). ✅
  4. Log in as dbrrds@umich.edu. Confirm login succeeds. ✅
  5. Log out; log in as tildon@umich.edu (BlueDemo2026t) — confirm persona switching works. ✅

For production/workshop: login still shows only the OIDC button. No regression. ✅

Adds a boolean config flag `auth.showPasswordLogin` that controls which login
method type is shown in the DSpace Angular login UI. The flag is an exclusive
toggle — exactly one type renders at a time, never both, never none.

  false (default): OIDC button shown, password form hidden
                   -> production and workshop are unchanged
  true:            password form shown, OIDC button hidden
                   -> for environments where DSpace OIDC is disabled (demo)

Background
----------
The demo environment uses oauth2-proxy at the gate for U-M WebLogin, and
DSpace's internal OIDC is intentionally disabled so testers can switch
personas via shared EPerson accounts. The existing UM customisation
(*ngIf="authMethod.authMethodType !== 'password'") removed the password form
entirely, leaving a blank login page once DSpace OIDC was disabled.

Changes
-------
src/config/auth-config.interfaces.ts
  Add showPasswordLogin?: boolean to AuthConfig interface.

src/config/default-app-config.ts
  Default showPasswordLogin: false in the auth block.

src/app/shared/log-in/log-in.component.ts
  Inject APP_CONFIG; read flag into public showPasswordLogin property.

src/app/shared/log-in/log-in.component.html
  Replace hard-coded *ngIf="... !== 'password'" with exclusive toggle:
    *ngIf="showPasswordLogin === (authMethod.authMethodType === 'password')"

src/app/shared/log-in/log-in.component.spec.ts
  Provide APP_CONFIG token; update assertion toBe(2) -> toBe(1)
  (only non-password method renders with default showPasswordLogin: false).

config/config.example.yml
  Add commented-out showPasswordLogin entry for operator reference.

Configuration
-------------
Enable for demo via Kubernetes frontend ConfigMap env-var:
  DSPACE_AUTH_SHOWPASSWORDLOGIN=true

The DSpace Angular config system will convert the string 'true' to a proper
boolean via getBooleanFromString (confirmed). Production and workshop must NOT
set this variable — omitting it leaves the default false.

Testing
-------
Unit tests: 2 specs pass (log-in.component.spec.ts).
See PLAN_DSPACE_ANGULAR_PASSWORD_LOGIN.md for full rationale, config flow
deep-dive, on-host debugging commands, and demo verification steps.
…lation

- environment.test.ts: add missing 'serverLocation' property required by BuildConfig
- item-withdraw/item-reinstate spec: pass required 'reason' arg to setWithDrawn assertion
- bitstream-format specs (6 files): rename stale enum values to current names
    Unknown   -> AS_IS_UNKNOWN
    Known     -> AS_IS_KNOWN
    Supported -> HIGHEST_LEVEL

These errors existed in the umich base branch before this branch was cut.
None are related to the showPasswordLogin feature change.
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

Adds a config-driven toggle to switch the login UI between password-only (demo) and non-password-only (prod/workshop), while also unblocking the test suite by fixing multiple pre-existing TypeScript spec compilation issues.

Changes:

  • Introduce auth.showPasswordLogin config flag (default false) and wire it into LogInComponent + template to exclusively render password vs non-password auth methods.
  • Update login unit test to provide APP_CONFIG and align assertions with the new rendering logic.
  • Fix several spec files to compile again (updated method signature + enum renames) and document the new config option in config.example.yml.

Reviewed changes

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

Show a summary per file
File Description
src/environments/environment.test.ts Adds missing serverLocation needed by BuildConfig in test environment.
src/config/default-app-config.ts Sets default auth.showPasswordLogin: false to preserve existing behavior.
src/config/auth-config.interfaces.ts Extends AuthConfig with optional showPasswordLogin flag.
src/app/shared/log-in/log-in.component.ts Injects APP_CONFIG and reads auth.showPasswordLogin into component state.
src/app/shared/log-in/log-in.component.html Replaces hardcoded password exclusion with config-driven exclusive toggle.
src/app/shared/log-in/log-in.component.spec.ts Provides APP_CONFIG in TestBed and updates expectation for new toggle behavior.
src/app/item-page/edit-item-page/item-withdraw/item-withdraw.component.spec.ts Updates setWithDrawn expectation to include new reason arg.
src/app/item-page/edit-item-page/item-reinstate/item-reinstate.component.spec.ts Updates setWithDrawn expectation to include new reason arg.
src/app/core/data/bitstream-data.service.spec.ts Updates renamed BitstreamFormatSupportLevel enum value.
src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts Updates renamed BitstreamFormatSupportLevel enum values.
src/app/admin/admin-registries/bitstream-formats/format-form/format-form.component.spec.ts Updates renamed BitstreamFormatSupportLevel enum value.
src/app/admin/admin-registries/bitstream-formats/edit-bitstream-format/edit-bitstream-format.component.spec.ts Updates renamed BitstreamFormatSupportLevel enum value.
src/app/admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts Updates renamed BitstreamFormatSupportLevel enum values.
src/app/admin/admin-registries/bitstream-formats/add-bitstream-format/add-bitstream-format.component.spec.ts Updates renamed BitstreamFormatSupportLevel enum value.
config/config.example.yml Documents the new auth.showPasswordLogin option for operators.
TODO.md Adds local task tracking for the feature branch (includes out-of-band kube follow-up).
DONE.md Records completed tasks/commits for the feature branch.
AGENTS.md Adds agent-oriented continuation notes for the branch/work.
PLAN_DSPACE_ANGULAR_PASSWORD_LOGIN.md Adds detailed rationale and deployment/verification plan for the toggle.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/app/shared/log-in/log-in.component.spec.ts
Comment thread PLAN_DSPACE_ANGULAR_PASSWORD_LOGIN.md
Comment thread PLAN_DSPACE_ANGULAR_PASSWORD_LOGIN.md Outdated
gkostin1966 and others added 2 commits April 29, 2026 14:33
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
item-withdraw.component.spec.ts:
  Change 'as HTMLElement' to 'as unknown as HTMLInputElement' to fix TS2352
  type error introduced by the reviewing agent (insufficient type overlap).
log-in.component.spec.ts:
  Replace TestBed.overrideProvider() inside an it() block (which throws
  'Cannot override provider when test module is already instantiated') with
  the correct approach: set component.showPasswordLogin = true directly on
  the component instance and call detectChanges().
  Also drop unreliable componentInstance.authMethod assertions on custom
  elements rendered via CUSTOM_ELEMENTS_SCHEMA.
All 3 log-in specs now pass.
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 20 out of 20 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread PULL_REQUEST.md Outdated
Comment thread src/app/shared/log-in/log-in.component.spec.ts
Comment thread src/app/item-page/edit-item-page/item-reinstate/item-reinstate.component.spec.ts Outdated
gkostin1966 and others added 3 commits April 29, 2026 15:00
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…nt ID

- Assert document.getElementById was called with 'withdrawReason' (the exact
  ID the component uses) rather than just trusting the spy ran.
- Assert setWithDrawn receives the exact string 'test-withdraw-reason' rather
  than jasmine.any(String), which would pass even with the wrong value.
…er directive, remove broken duplicate it block (DEEPBLUE-466)
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 20 out of 20 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread TODO.md
Comment thread src/config/auth-config.interfaces.ts Outdated
Comment thread config/config.example.yml Outdated
Comment thread src/app/shared/log-in/log-in.component.spec.ts
gkostin1966 and others added 3 commits April 29, 2026 15:44
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…operty mutation instead

TestBed.overrideProvider() throws 'Cannot override provider when test module has
already been instantiated' when called inside an it() block, even after
fixture.destroy(). Destroying the fixture does not reset the TestBed module state.
The working approach is to set component.showPasswordLogin = true directly on the
component instance after the module is instantiated, then call detectChanges().
This correctly re-renders the template with the new value.
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 20 out of 20 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +130 to +136
it('should render a log-in container component for each auth method available', () => {
const loginContainers = fixture.debugElement.queryAll(By.css('ds-log-in-container'));
expect(loginContainers.length).toBe(2);
const loginContainers = fixture.debugElement.queryAll(By.directive(LogInContainerComponent));
// authMethodsMock = [password, shibboleth]. With showPasswordLogin: false (default),
// only the shibboleth container renders (exclusive toggle). The outer container count
// and the inner rendered method component both confirm which method is shown.
expect(loginContainers.length).toBe(1);
expect(loginContainers[0].componentInstance.authMethod.authMethodType).toBe('shibboleth');
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

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

The test name says it renders a container for each available auth method, but the new exclusive-toggle behavior intentionally renders only one method even when multiple are available. Renaming the it(...) description to match the assertions (e.g., that non-password methods render when showPasswordLogin is false) will prevent confusion when reading failures.

Copilot uses AI. Check for mistakes.
@gkostin1966 gkostin1966 merged commit 4f1b202 into umich Apr 29, 2026
4 of 8 checks passed
@gkostin1966 gkostin1966 deleted the show-password-login branch April 29, 2026 20:10
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.

2 participants