Skip to content

Api: Convert numbered ids to strings before lookups#1520

Open
MrDirkelz wants to merge 102 commits into
mainfrom
api-parse-numbers-to-strings-for-id-lookup
Open

Api: Convert numbered ids to strings before lookups#1520
MrDirkelz wants to merge 102 commits into
mainfrom
api-parse-numbers-to-strings-for-id-lookup

Conversation

@MrDirkelz

Copy link
Copy Markdown
Collaborator

No description provided.

…zation with support for dynamic group assignments and JWT verification
…ppearance

- Removed "always" condition type and defaulted to "authenticated" in AuthProviderGroupMappings.vue
- Updated OAuth terminology to "auth provider" in AuthProviderOverview.vue
- Enhanced database initialization to check socket connection before revoking access in database.ts
- Modified AuthProviderCondition type to remove "always" condition in dto.ts
- Added .claudeignore for dependency and build artifacts
- Created CLAUDE.md for project overview and development workflow
- Introduced dry_run_mappings.json for future mappings
- Added AuthProviderAppearance.vue for customizable appearance settings
- Created AuthProviderAuthConfig.vue for authentication configuration inputs
- Implemented AuthProviderClaimMappings.vue for JWT claim mapping management
- Added AuthProviderFormActions.vue for save, delete, and close actions
- Created AuthProviderFormErrors.vue for displaying form validation errors
- Introduced AuthProviderIconSection.vue for icon upload and opacity settings
- Added AuthProviderLabelAndType.vue for provider label input
- Implemented AuthProviderUserFieldMappings.vue for user field claim overrides
…cation handling; modify GlobalConfigDto documentation; enhance JWT processing; adjust Socketio user details handling; refine SideBar visibility permissions
…ken function for OAuth handling; update database tests for connection state management; refine applyLocalChangeAck method to handle partial local changes
…er and globalConfig ACL entries; initialize identities array on User documents
…balConfig ACL entries for groups; initialize identities array on User documents
…ched identities; enhance user provisioning logic in AuthIdentityService; clear accessMap on revoked documents in database tests
… tests to manage accessMap for document deletion scenarios
…fig to accessMap; refactor error handling in sync functions; update AuthProviderUserFieldMappings to use v-model for provider
…n sync functions; update tests to include AuthProvider and GlobalConfig document types
…e for open state in dialog components; enhance access verification with default empty array for memberOf
…gement

- Updated AuthProviderAuthConfig.vue to utilize a model for provider properties instead of individual props.
- Simplified event emissions by directly binding model values in AuthProviderFormModal.vue and related components.
- Enhanced AuthProviderGroupMappings.vue with inline editing capabilities for conditions and improved UI for group selection.
- Adjusted AuthProviderIconSection.vue to directly bind icon opacity to the provider model.
- Removed unused claimMappings from AuthProviderDto in dto.ts.
- Improved createEditable utility to optimize filtering and modification tracking.
- Added useDexieLiveQueryAsEditable utility for enhanced editable state management.
- Updated LCombobox.vue to support inline tags for better user experience.
- Enhanced modal styling in LModal.vue for improved visual consistency.
…to optimize the `accessMap` listener in the database.
… test coverage for auth provider components and logic.
MrDirkelz and others added 30 commits April 15, 2026 10:39
…alidation

Collapse the duplicated redirect-handled / no-callback branches in
setupAuth() for both app and cms: the provider-resolution, header/socket
wiring, and token fetch now run in one shared block after
handleRedirectCallbackIfPresent(). CMS preserves its reset + open-
provider-modal behavior on token failure for the returning-user path;
app keeps swallowing token errors since public browsing is a valid
unauthenticated state.

Pull form-local concerns out of useAuthProviders and into FormModal
where they belong: staging JWT config (with a comment explaining the
singleton sync-block it protects against), per-field validation,
isFormValid, hasAttemptedSubmit, and the staging-vs-singleton dirty
diff. FormModal now exposes isDirty and hasAttemptedSubmit via
defineModel, and handles duplicate via an imperative prepareForDuplicate
hook so in-progress JWT edits carry over to the clone without the
staging watcher wiping them.

Rework the composable around the slimmer surface: authProviderConfig
computed, isProviderEdited helper, isFormDirty ref bound to FormModal's
v-model, and saveProvider now takes the stagingConfig as an argument
instead of reading it from its own state. The showModal close-cleanup
watcher uses flush: 'sync' so the route guard and the composable spec
harness observe the reset synchronously. AuthProviderOverview's
destructure drops from 38 to 28 bindings and wires the new FormModal
API, including a formModalRef for the duplicate handoff.

Tighten auth provider credential validation so the save button and
error messages reject obvious garbage: domain must be a plain RFC 1123
hostname (no scheme, path, port, or whitespace); client ID must be at
least 8 characters with no whitespace; audience must parse as an
absolute http(s) URL. Rules are intentionally provider-agnostic rather
than Auth0-only since the auth layer is slated to accept other OIDC
providers.

Update useAuthProviders.spec.ts to match: isDirty-tracking and
isFormValid describe blocks removed (those now belong to a FormModal
component spec), new isDirtyAny-route-guard and isProviderEdited
coverage, saveProvider tests pass an explicit stagingConfig, and a new
test verifies that a non-empty stagingConfig is committed into the
singleton on save.
…n set

Rename `groupId: string` to `groupIds: string[]` on AuthProviderGroupMapping
so one condition set can grant membership in multiple local groups at once,
instead of forcing users to duplicate the same conditions across N mappings.
The CMS UI was already driving a multi-select LCombobox and storing its
per-row selection as `string[][]` — this refactor makes the underlying data
shape match what the UI already supported.

DTO and shared type: rename the field on both copies
(api/src/dto/AuthProviderConfigDto.ts + shared/src/types/dto.ts) and swap
class-validator from @IsString+@isnotempty to @isarray+@ArrayNotEmpty+
@IsString({each:true}), preserving the "must assign at least one group"
guarantee the scalar used to provide.

API runtime: evaluateGroupAssignments reads mapping.groupIds, falling back
to legacy `groupId` when absent so existing singleton docs in the wild keep
resolving correctly until they're rewritten. On match, every entry in
groupIds is added to assignedGroups. Left a TODO(post-migration) marking
the fallback for deletion once all deployments have saved at least once
post-release.

Write-path normalizer: processAuthProviderConfigDto now walks
doc.providers[*].groupMappings[*] and coerces `{ groupId }` to
`{ groupIds: [groupId] }`, deleting the legacy key. Any write from an old
client (pre-refactor CMS, pre-refactor add-auth-provider.ts, or a direct
API call) gets transparently migrated on its first save, which lets the
DTO validator require `groupIds` unconditionally.

CMS GroupMappings.vue: load staging as `m.groupIds ?? legacy-fallback`,
write back via renamed updateMappingGroupIds with shallow-equal echo
guard, update the search filter to match any assigned group, and rework
the helper copy / combobox placeholders to use plural phrasing. FormModal
rejects save when any mapping has zero groups assigned so the Save button
stays honest instead of bouncing off server validation.

add-auth-provider.ts: interactive prompt now accepts comma-separated group
IDs per rule, the AUTO_GROUP_MAPPINGS shape is migrated, and the
auto-vs-extra merge keys on a sorted-joined groupIds signature so a
user-supplied mapping targeting the exact same group set overrides the
auto default. Different group sets stay as distinct rules.

Tests: authIdentity.service.spec.ts updates 6 fixtures and adds coverage
for multi-group assignment, cross-mapping de-duplication, the legacy
`groupId` fallback path, and empty-groupIds skipping.
processAuthProviderConfigDto.spec.ts adds 5 cases for the normalizer
(legacy→new, both keys present, neither key, missing providers, missing
groupMappings). GroupMappings.spec.ts updates fixtures and adds tests for
LCombobox-driven multi-select and legacy-shape render.
DefaultPermissionsDto redeclared memberOf locally while extending
_baseDto, duplicating the single field _contentBaseDto exists to
provide. Switch the API class and the shared-type mirror to extend
the content base so memberOf is inherited, keeping the DTO in line
with every other content-bearing document.
- api main.spec: mock useGlobalFilters on the Nest app stub
- app ProfileMenu/TopBar specs: toggle isAuthPluginInstalled so
  useAuthWithPrivacyPolicy returns the mocked auth0 instead of the
  unauthenticated fallback
- cms ProfileMenu/SideBar/waitUntilAuth0IsLoaded specs: add
  isAuthPluginInstalled to the @/auth vi.mock so imports resolve
setupAuth ran before app.use(router), so router.replace() to strip the
Auth0 callback query params threw "Cannot read properties of undefined
(reading '_s')" from vue-router internals. Drop the router dependency
from setupAuth and use history.replaceState for the URL cleanup instead.
The global-groups button never appeared because DefaultPermissions is
not mirrored into Dexie (by design — see sync.ts), yet useAuthProviders
was reading it via a Dexie live query and always got undefined. Switch
to ApiLiveQueryAsEditable, mirroring the AuthProviderConfig pattern,
and persist saves through the query instead of db.upsert.
…cs, and saveDefaultGroups is verified against the captured change request instead of Dexie.
llowedHeaders might have to be made configurable. The shared client library supports injection of custom headers (use for x-auth-provider-id and the Authorization header), and could potentially be used for other custom headers as well.
…ough the change feed, the handler now evicts the deleted provider from providerCache and its JWKS client from jwksClients. Also evicts any auto-group-mapping cache for the deleted doc ID. This means deleting a provider immediately cuts off access — no server restart needed.

Fix 2 — Generic error messages: resolveOrDefault now always throws "Invalid authentication token" to the client, regardless of the underlying failure (expired, wrong signature, wrong audience, etc.). The real error is logged at warn level with the providerId for debugging. Attackers can no longer distinguish between clock issues, key mismatches, or audience misconfigurations from the HTTP response.
Co-authored-by: Ivan Slabbert <ivanslabbert@users.noreply.github.com>
…fix duplicate button

- After JWT verification, check that the token's `azp`/`client_id` claim
  matches the provider's configured clientId. Prevents tokens issued for
  one client from being accepted under a different provider's context.
- Fix duplicate button in AutoGroupMappingModal: remove snapshot reset
  after duplicate so isDirty stays true and save is enabled.
- Update evaluateGroupAssignments tests to use AND logic (`.every`)
  matching the updated implementation.
Optional name and summary fields on AutoGroupMappingsDto let admins
label and describe each mapping. The display card shows the name as
the title (falling back to the condition summary) with the summary
as a subtitle. Both fields are included in the overview search filter.
Provider-less AutoGroupMappings documents (no providerId) now serve as
global default groups for all users, replacing the DefaultPermissions
singleton. The DefaultPermissions DTO, processor, enum value, and all
references are removed.

- providerId is now optional on AutoGroupMappingsDto
- authIdentity.service derives default groups by querying AutoGroupMappings
  with no providerId instead of querying DefaultPermissions
- CMS modal derives global mode from empty providerId (no special prop)
- Display card shows globe icon for provider-less mappings
- Collapsed name/summary into a single description field
- Setup script option 3 creates AutoGroupMappings instead of DefaultPermissions
- Add "Global (All Users)" option to the provider filter dropdown
- Use warning color scheme on display card badges for global mappings
- Add gap between filter bar and first card
- Update global mapping message to guide users to select a provider
- Fix shrinking icon in LBadge with shrink-0
- Re-add lastChangeRequest variable in useAuthProviders spec
- Rename GroupMappings spec to AutoGroupMappingConditions spec
- Fix AuthProviderSelectionModal spec for updated empty state text
- Add no-divider prop to auth provider FormModal to remove the
  divider line between content and action buttons
- Remove border-t from FormActions component
- Remove DefaultPermissions references from app/src/sync.spec.ts
- Add tests for multiple global and provider-specific group mappings
  merging and deduplication in authIdentity.service.spec.ts
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.

1 participant