Auth Slice

Registered by AuthModule under the key auth, with the persistent meta-reducer attached through AUTH_CONFIG_TOKEN:

StoreModule.forFeature('auth', authReducer, AUTH_CONFIG_TOKEN),
EffectsModule.forFeature([AuthEffects, UserStatusEffects]),

Shape

The slice is a combineReducers of three sub-states.

export interface AuthState {
    auth: LoginState;
    recoverPasswordRequest: RecoverPasswordRequestState;
    newPasswordRequest: NewPasswordRequestState;
}

export interface LoginState {
    loggedIn: boolean;
    authToken: string;
    user: Partial<User>;
    isUserLoaded: boolean;
    statusLoading: boolean;
    dashboardStatusV2: SupplierDashboardStatusV2Dto;
}

export interface RecoverPasswordRequestState { isPending: boolean; requestSent: boolean; error: string; }
export interface NewPasswordRequestState     { isPending: boolean; requestSend: boolean; error: string; }

There are two dashboard-status representations. user.dashboardStatus (SupplierDashboardStatusType: onboarding \| welcome \| inactive_dashboard \| active) drives the permission calculation, while dashboardStatusV2 (SupplierDashboardStatusTypeV2 from the API package) is the newer server-side status used by GlobalSubscriptionsService. Read the one the surrounding code reads.

Action types

src/app/core/auth/_actions/actions.enums.ts

Member String

Login

[Login] Action

Logout

[Logout] Action

Register

[Register] Action

UserRequested

[Request User] Action

UserLoaded

[Load User] Auth API

UserUpdated

[Update User] Update User

GetUserByToken

[User] Get User By Token

UserConfirmed2FA

[User Confirmed 2FA] Confirmed 2FA

UserConfirmed2FAError

[User Confirmed 2FA] Confirmed 2FA Error

UserPermissionsRequested

[User Permissions] User permissions requested

UserPermissionsLoaded

[User Permissions] User permissions loaded

UserPermissionAdded

[User Permissions] User permission added

UserPermissionRemoved

[User Permissions] User permission removed

UserStatusUpdateRequested

[Request User Status] User status update requested

UserStatusUpdated

[Update User Status] User status updated

UserDashboardStatusRequested

[User Dashboard Status] User dashboard status requested

UserDashboardStatusLoaded

[User Dashboard Status] User dashboard status loaded

RecoverPasswordRequest / …Error / …Success / …Reset

[Recover Password] …

NewPasswordRequest / …Error / …Success / …Reset

[New Password] …

noAction ('NO_ACTION') is a no-op used by init$ when there is no stored token.

Reducer behaviour

Action State change

login

loggedIn: true, store authToken, isUserLoaded: false, statusLoading: true

logout

loggedIn: false (the effect then clears storage and reloads the page)

register

Store authToken, loggedIn: true, clear user

userLoaded

Set user, isUserLoaded: true, statusLoading: false

userUpdated

Replace user, isUserLoaded: true

userStatusUpdateRequested

statusLoading: true

userStatusUpdated

Merge status into user, statusLoading: false

userDashboardStatusLoaded

Set dashboardStatusV2

userConfirmed2Fa

Replace user

userPermissionsLoaded

Set user.permissions

userPermissionAdded

union([permission], state.user.permissions)

userPermissionRemoved is defined as an action but has no on() handler in userReducer. Permission revocation at runtime goes through NgxPermissionsService.removePermission() instead — for example in DocusignVerificationService. The store copy stays stale until the next recalculation.

Effects

src/app/core/auth/_effects/auth.effects.ts

Effect Trigger Behaviour

init$

app start (defer)

Reads localStorage[authTokenKey]; dispatches login or noAction.

login$

login

Writes the token to localStorage; dispatches userRequested.

register$

register

Same as login$.

logout$

logout

stateManager.clear(), removes the token, reloads the page after 1 s. { dispatch: false }.

loadUser$

userRequested

Skips when the user is already loaded; calls getUserByToken(); eventLogger.identify(user); dispatches userLoaded, userPermissionsRequested, userDashboardStatusRequested, loadBalance. Falls back to logout() when no user comes back.

getUserByToken$

getUserByToken

Re-fetches the user; dispatches userUpdated.

updateUserStatus$

userStatusUpdateRequested

getSupplierStatus(id) → userStatusUpdated({ status: Status.fromDto(status) }).

userUpdated$

userUpdated

→ userPermissionsRequested.

userStatusUpdated$

userStatusUpdated

→ userPermissionsRequested.

userDashboardStatusRequested$

userDashboardStatusRequested

getSupplierDasboardStatusV2(user.id) → userDashboardStatusLoaded.

loadedUserPermissions$

userPermissionsRequested

PermissionsService.getUserPermissions(user) → userPermissionsLoaded.

recoverUserPasswordEmail$

recoverPasswordEmailRequest

requestPassword() → success or error action.

newUserPasswordRequest$

newPasswordRequest

confirmPasswordReset() then executePasswordChange().

UserStatusEffects (_effects/user-status.effects.ts) is registered alongside and handles status-driven follow-up work.

loadUser$ uses filter((_, isLoaded) ⇒ !isLoaded). The second argument of RxJS filter is the emission index, not the withLatestFrom value — for the first emission it is 0, which is falsy, so the filter passes. The guard therefore only really protects against repeat emissions.

Selectors

src/app/core/auth/_selectors/auth.selectors.ts

Session

Selector Returns

selectAuthState

The whole auth feature state

selectLoginState

state.auth (the LoginState)

isLoggedIn / isLoggedOut

Session boolean

selectCurrentAuthToken

Raw token string

selectIsUserLoaded

Whether the user object has arrived

User

Selector Returns

selectCurrentUser

The User

selectCurrentUserId

user.id (the supplier key)

selectCurrentUserStatus

user.status

selectSupplierStatus

user.status.supplierStatus

selectSupplierOnboardSchema

user.schema

selectOnboardingTemplateCode

user.onboardingTemplateCode

selectDashboardStatusV2

dashboardStatusV2

Derived state

Selector Condition

selectIsSupplierActive

supplierStatus === Active

selectIsSupplierPending

supplierStatus === Pending

selectIsSupplierPendingActivation

supplierStatus === PendingActivation

selectUserCancellationStatus

user.cancelationStatus

selectIsSupplierCancelled

cancelationStatus === Canceled and supplierStatus === Suspended

selectHasInstantAdvHistory

status.hasInstantAdvHistory

selectActiveInstantAdv

status.activeInstantAdvance

selectLtcActive

status.hasActiveLTC

selectRenewLTCSigned

status.renewLTCSigned

selectAmazonApiSwitching

user.amazonApiSwitching

selectIsLegalSigned

status.legalSigned

currentUserPermissions

The hierarchical Permission[]

The permissions slice

Registered separately by ThemeModule under the key permissions, using @ngrx/entity:

export interface State extends EntityState<Permission> {
    isAllPermissionsLoaded: boolean;
}

export const adapter = createEntityAdapter<Permission>({ selectId: entity => entity.id });

Handled actions: allPermissionsRequested, allPermissionsLoaded (setAll), permissionAdded (addOne), permissionRemoved (removeOne).

Legacy sub-slices

user.reducers.ts / role.reducers.ts (with their actions, effects, selectors and users.datasource.ts / roles.datasource.ts) are inherited from the admin template the project started from. UserActionTypes and RoleActionTypes exist but no supplier-facing flow dispatches them.