@atlasauth/angular 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/esm2022/lib/appearance.mjs +1 -1
  3. package/dist/esm2022/lib/atlas.service.mjs +40 -3
  4. package/dist/esm2022/lib/atlas.ui.mjs +7 -1
  5. package/dist/esm2022/lib/components/attempt-flow.component.mjs +419 -11
  6. package/dist/esm2022/lib/components/flow-controller.mjs +132 -2
  7. package/dist/esm2022/lib/components/impersonation-banner.component.mjs +75 -0
  8. package/dist/esm2022/lib/components/organization-audit-log.component.mjs +115 -0
  9. package/dist/esm2022/lib/components/organization-audit-log.mjs +40 -0
  10. package/dist/esm2022/lib/components/organization-profile.component.mjs +602 -27
  11. package/dist/esm2022/lib/components/policy-host.mjs +254 -0
  12. package/dist/esm2022/lib/components/recovery-codes.component.mjs +122 -0
  13. package/dist/esm2022/lib/components/sign-in.component.mjs +47 -4
  14. package/dist/esm2022/lib/components/sign-up-form.component.mjs +136 -10
  15. package/dist/esm2022/lib/components/sign-up.component.mjs +86 -8
  16. package/dist/esm2022/lib/i18n.mjs +61 -1
  17. package/dist/esm2022/lib/provide-atlas.mjs +4 -2
  18. package/dist/esm2022/lib/types.mjs +1 -1
  19. package/dist/esm2022/lib/version.mjs +2 -2
  20. package/dist/esm2022/public-api.mjs +6 -1
  21. package/dist/fesm2022/atlasauth-angular.mjs +2129 -95
  22. package/dist/fesm2022/atlasauth-angular.mjs.map +1 -1
  23. package/dist/lib/appearance.d.ts +1 -1
  24. package/dist/lib/atlas.service.d.ts +23 -1
  25. package/dist/lib/atlas.ui.d.ts +3 -1
  26. package/dist/lib/components/attempt-flow.component.d.ts +61 -2
  27. package/dist/lib/components/flow-controller.d.ts +73 -1
  28. package/dist/lib/components/impersonation-banner.component.d.ts +27 -0
  29. package/dist/lib/components/organization-audit-log.component.d.ts +34 -0
  30. package/dist/lib/components/organization-audit-log.d.ts +25 -0
  31. package/dist/lib/components/organization-profile.component.d.ts +55 -6
  32. package/dist/lib/components/policy-host.d.ts +88 -0
  33. package/dist/lib/components/recovery-codes.component.d.ts +26 -0
  34. package/dist/lib/components/sign-in.component.d.ts +2 -0
  35. package/dist/lib/components/sign-up-form.component.d.ts +22 -4
  36. package/dist/lib/components/sign-up.component.d.ts +13 -0
  37. package/dist/lib/provide-atlas.d.ts +3 -1
  38. package/dist/lib/types.d.ts +6 -0
  39. package/dist/lib/version.d.ts +1 -1
  40. package/dist/public-api.d.ts +5 -0
  41. package/package.json +3 -3
@@ -31,7 +31,7 @@ export interface DesignTokens {
31
31
  spacingUnit?: string;
32
32
  }
33
33
  /** Every element a customer may target. Named for what it IS, not where it sits. */
34
- export type ElementKey = 'root' | 'card' | 'headerTitle' | 'headerSubtitle' | 'formField' | 'formFieldLabel' | 'formFieldInput' | 'formFieldError' | 'formButtonPrimary' | 'formButtonSecondary' | 'socialButton' | 'dividerText' | 'footerAction' | 'avatar' | 'menu' | 'menuItem' | 'badge';
34
+ export type ElementKey = 'root' | 'card' | 'headerTitle' | 'headerSubtitle' | 'formField' | 'formFieldLabel' | 'formFieldInput' | 'formFieldError' | 'formButtonPrimary' | 'formButtonSecondary' | 'socialButton' | 'dividerText' | 'footerAction' | 'avatar' | 'menu' | 'menuItem' | 'list' | 'listItem' | 'badge';
35
35
  export interface Appearance extends DesignAppearance {
36
36
  /** A prebuilt token theme to start from (pre-design-system themes). */
37
37
  baseTheme?: keyof typeof THEMES;
@@ -1,6 +1,7 @@
1
1
  import { OnDestroy, Signal } from '@angular/core';
2
2
  import { Observable } from 'rxjs';
3
- import { FapiClient, type ErrorLike, type ProviderToken, type SignOutOptions, type SignOutResult, type SignOutEvent, type SignOutListener } from '@atlasauth/js';
3
+ import { AtlasOrganizationAuditLog } from './components/organization-audit-log';
4
+ import { FapiClient, type ErrorLike, type OrganizationAuditLogOptions, type ProviderToken, type SignOutOptions, type SignOutResult, type EndImpersonationResult, type SignOutEvent, type SignOutListener } from '@atlasauth/js';
4
5
  import { type ProtectCondition } from '@atlasauth/authz';
5
6
  import { type Appearance, type AppearanceRender, type InstanceDesign } from './appearance';
6
7
  import { type Catalog } from './i18n';
@@ -56,6 +57,7 @@ export declare class AtlasService implements OnDestroy {
56
57
  readonly pendingAttempt: {
57
58
  id: string;
58
59
  status: string;
60
+ policyToken?: string;
59
61
  } | null;
60
62
  private readonly _status;
61
63
  private readonly _user;
@@ -124,6 +126,19 @@ export declare class AtlasService implements OnDestroy {
124
126
  * `appearance.instanceDesign: false`.
125
127
  */
126
128
  loadInstanceDesign(): Promise<InstanceDesign | null>;
129
+ /**
130
+ * The active organization's audit trail, for its admins: `state` is a signal
131
+ * of `{ entries, loading, forbidden, hasMore }`, one page at a time with
132
+ * `loadMore()`. `action` narrows it (exact, or a prefix ending in `.`). It
133
+ * follows the active organization; call `destroy()` when done. The peer of
134
+ * React's `useOrganizationAuditLog`.
135
+ */
136
+ organizationAuditLog(options?: OrganizationAuditLogOptions): AtlasOrganizationAuditLog;
137
+ /**
138
+ * Re-authenticate the signed-in user with their password (a step-up), for an
139
+ * action the server answered with STEP_UP_REQUIRED. Rejects when refused.
140
+ */
141
+ reauthenticate(password: string): Promise<void>;
127
142
  /** A fresh {@link FapiClient} for driving a sign-in/sign-up flow. */
128
143
  createFapiClient(): FapiClient;
129
144
  /**
@@ -159,6 +174,13 @@ export declare class AtlasService implements OnDestroy {
159
174
  * unless `{ frontchannel: false }`.
160
175
  */
161
176
  signOut(options?: SignOutOptions): Promise<SignOutResult>;
177
+ /**
178
+ * End the active impersonation ("return to admin"): the impersonator's own
179
+ * session on this browser becomes active again with no sign-in
180
+ * (`resumed: true`); with none, another account signed in here is adopted,
181
+ * or this browser is signed out.
182
+ */
183
+ endImpersonation(): Promise<EndImpersonationResult>;
162
184
  /**
163
185
  * Switch the active organization (or `null` for the personal account). The
164
186
  * new token carries the new org claims, so the app's permission checks update
@@ -10,6 +10,8 @@ import { UserButtonComponent } from './components/user-button.component';
10
10
  import { OrganizationSwitcherComponent } from './components/organization-switcher.component';
11
11
  import { UserProfileComponent } from './components/user-profile.component';
12
12
  import { OrganizationProfileComponent } from './components/organization-profile.component';
13
+ import { OrganizationAuditLogComponent } from './components/organization-audit-log.component';
14
+ import { AtlasPoliciesDirective, PolicyAcceptStepComponent, PolicyGateComponent } from './components/policy-host';
13
15
  /**
14
16
  * Every standalone directive and component the SDK ships. Import the array in a
15
17
  * standalone component's `imports`, or rely on `AtlasModule` re-exporting it for
@@ -19,4 +21,4 @@ import { OrganizationProfileComponent } from './components/organization-profile.
19
21
  * @Component({ standalone: true, imports: [...ATLAS_UI], template: '…' })
20
22
  * ```
21
23
  */
22
- export declare const ATLAS_UI: readonly [typeof AtlasSignedInDirective, typeof AtlasSignedOutDirective, typeof AtlasLoadingDirective, typeof AtlasLoadedDirective, typeof AtlasProtectDirective, typeof AtlasRootDirective, typeof SignInComponent, typeof SignUpComponent, typeof UserButtonComponent, typeof OrganizationSwitcherComponent, typeof UserProfileComponent, typeof OrganizationProfileComponent];
24
+ export declare const ATLAS_UI: readonly [typeof AtlasSignedInDirective, typeof AtlasSignedOutDirective, typeof AtlasLoadingDirective, typeof AtlasLoadedDirective, typeof AtlasProtectDirective, typeof AtlasRootDirective, typeof SignInComponent, typeof SignUpComponent, typeof UserButtonComponent, typeof OrganizationSwitcherComponent, typeof UserProfileComponent, typeof OrganizationProfileComponent, typeof OrganizationAuditLogComponent, typeof AtlasPoliciesDirective, typeof PolicyAcceptStepComponent, typeof PolicyGateComponent];
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter } from '@angular/core';
2
- import { type AttemptView, type CaptchaController, type FieldError } from '@atlasauth/js';
2
+ import { type AttemptView, type CaptchaController, type FieldError, type MfaEnrollmentController, type MfaEnrollmentState, type MfaEnrollmentStrategy } from '@atlasauth/js';
3
3
  import { type ElementKey } from '../appearance';
4
4
  import * as i0 from "@angular/core";
5
5
  /**
@@ -50,6 +50,48 @@ export declare class AttemptFlowComponent {
50
50
  submitFlow: EventEmitter<Record<string, string>>;
51
51
  /** Emits when the user picks a first factor the server must send first (an emailed code). */
52
52
  chooseFactor: EventEmitter<"email_code">;
53
+ /**
54
+ * Offer "Email me a code instead" at the second factor (the instance's
55
+ * `account.emailSecondFactor`); `emailSecondFactor` asks for it and
56
+ * `emailedSecondFactor` reports how it went.
57
+ */
58
+ offerEmailSecondFactor: boolean;
59
+ /** `AtlasFlowController.emailSecondFactor()`: in flight, where it went, or why not. */
60
+ emailedSecondFactor: {
61
+ busy?: boolean;
62
+ sentTo?: string;
63
+ error?: string;
64
+ } | null;
65
+ emailSecondFactor: EventEmitter<void>;
66
+ /**
67
+ * Offer "Text me a code instead" at the second factor (where the app offers
68
+ * texted codes, `AtlasFlowController.mfaChoices().sms`); `smsSecondFactor`
69
+ * asks for it and `textedSecondFactor` reports how it went.
70
+ */
71
+ offerSmsSecondFactor: boolean;
72
+ /** `AtlasFlowController.smsSecondFactor()`: in flight, where it went, or why not. */
73
+ textedSecondFactor: {
74
+ busy?: boolean;
75
+ sentTo?: string;
76
+ error?: string;
77
+ } | null;
78
+ smsSecondFactor: EventEmitter<void>;
79
+ /**
80
+ * The MFA enrolment step (`AtlasFlowController.enrollment` and
81
+ * `enrollmentState()`): the authenticator app's QR code and setup key, or a
82
+ * texted code. Null: the step asks for two authenticator codes only.
83
+ */
84
+ enrollment: MfaEnrollmentController | null;
85
+ enrollmentState: MfaEnrollmentState | null;
86
+ /**
87
+ * The instance's `account.emailVerification`. On `link` a sign-up's
88
+ * verification step has nothing to type: it says to open the emailed link
89
+ * while the flow polls, and offers a resend (`resend`).
90
+ */
91
+ emailVerification: string;
92
+ resend: EventEmitter<void>;
93
+ /** The user declined a policy the sign-in was waiting on (`needs_policy_acceptance`): cancel the attempt. */
94
+ policyDeclined: EventEmitter<string>;
53
95
  protected values: Record<string, string>;
54
96
  protected t(key: string, vars?: Record<string, string>): string;
55
97
  /** A server error in the app's language (`error.<reason>`, else the server's message). */
@@ -57,18 +99,35 @@ export declare class AttemptFlowComponent {
57
99
  protected cls(key: ElementKey, base: string): string;
58
100
  protected setValue(name: string, value: string): void;
59
101
  protected onSubmit(event: Event): void;
102
+ /** The shared enrolment step is drawn (a controller was passed and the flow is enrolling). */
103
+ protected enrolling(): boolean;
104
+ protected chooseMethod(method: MfaEnrollmentStrategy): void;
105
+ protected resendEnrollment(): void;
106
+ protected otherMethods(state: MfaEnrollmentState): MfaEnrollmentStrategy[];
107
+ protected setupKey(secret: string): string;
108
+ /** The submit button's label key (enrolment: "Text me a code" before the number is sent). */
109
+ protected submitKey(): string;
110
+ protected showSmsSecondFactor(): boolean;
111
+ /** Where the texted second-factor code went (masked), once it was sent. */
112
+ protected smsSecondFactorSentTo(): string | null;
60
113
  protected formErrors(): FieldError[];
61
114
  protected fieldErrorsFor(name: string): FieldError[];
62
115
  private step;
63
116
  protected showCaptcha(): boolean;
64
117
  /** The first factors on offer at a `needs_first_factor` step (empty on any other). */
65
118
  private offered;
119
+ protected linkOnly(): boolean;
120
+ protected showEmailSecondFactor(): boolean;
121
+ /** Where the emailed second-factor code went (masked), once it was sent. */
122
+ protected emailSecondFactorSentTo(): string | null;
66
123
  protected showEmailCodeOption(): boolean;
67
124
  /** The "we sent a code to …" line on the code step. */
68
125
  protected codeSentText(): string | null;
126
+ /** The attempt is `needs_policy_acceptance`. */
127
+ protected awaitingPolicies(): boolean;
69
128
  protected showSubmit(): boolean;
70
129
  protected fields(): StepField[];
71
130
  static ɵfac: i0.ɵɵFactoryDeclaration<AttemptFlowComponent, never>;
72
- static ɵcmp: i0.ɵɵComponentDeclaration<AttemptFlowComponent, "atlas-attempt-flow", never, { "attempt": { "alias": "attempt"; "required": false; }; "busy": { "alias": "busy"; "required": false; }; "errors": { "alias": "errors"; "required": false; }; "sessionKept": { "alias": "sessionKept"; "required": false; }; "titleKey": { "alias": "titleKey"; "required": false; }; "captcha": { "alias": "captcha"; "required": false; }; "firstFactors": { "alias": "firstFactors"; "required": false; }; "preparedFactor": { "alias": "preparedFactor"; "required": false; }; }, { "submitFlow": "submitFlow"; "chooseFactor": "chooseFactor"; }, never, never, true, never>;
131
+ static ɵcmp: i0.ɵɵComponentDeclaration<AttemptFlowComponent, "atlas-attempt-flow", never, { "attempt": { "alias": "attempt"; "required": false; }; "busy": { "alias": "busy"; "required": false; }; "errors": { "alias": "errors"; "required": false; }; "sessionKept": { "alias": "sessionKept"; "required": false; }; "titleKey": { "alias": "titleKey"; "required": false; }; "captcha": { "alias": "captcha"; "required": false; }; "firstFactors": { "alias": "firstFactors"; "required": false; }; "preparedFactor": { "alias": "preparedFactor"; "required": false; }; "offerEmailSecondFactor": { "alias": "offerEmailSecondFactor"; "required": false; }; "emailedSecondFactor": { "alias": "emailedSecondFactor"; "required": false; }; "offerSmsSecondFactor": { "alias": "offerSmsSecondFactor"; "required": false; }; "textedSecondFactor": { "alias": "textedSecondFactor"; "required": false; }; "enrollment": { "alias": "enrollment"; "required": false; }; "enrollmentState": { "alias": "enrollmentState"; "required": false; }; "emailVerification": { "alias": "emailVerification"; "required": false; }; }, { "submitFlow": "submitFlow"; "chooseFactor": "chooseFactor"; "emailSecondFactor": "emailSecondFactor"; "smsSecondFactor": "smsSecondFactor"; "resend": "resend"; "policyDeclined": "policyDeclined"; }, never, never, true, never>;
73
132
  }
74
133
  export {};
@@ -1,5 +1,5 @@
1
1
  import { WritableSignal } from '@angular/core';
2
- import { FapiClient, type CaptchaController, type FlowState, type InstanceSettings } from '@atlasauth/js';
2
+ import { FapiClient, PolicyAcceptanceController, type CaptchaController, type FlowState, type InstanceSettings, type MfaChoices, type MfaEnrollmentController, type MfaEnrollmentState } from '@atlasauth/js';
3
3
  /**
4
4
  * The server-driven sign-in / sign-up engine, shared by `<atlas-sign-in>` and
5
5
  * `<atlas-sign-up>` — the Angular counterpart of React's `useFlow` hook.
@@ -26,6 +26,11 @@ export declare class AtlasFlowController {
26
26
  * resolves, or when the server could not be reached.
27
27
  */
28
28
  readonly settings: WritableSignal<InstanceSettings>;
29
+ /**
30
+ * The method this browser last signed in with (`password`, `oauth_github`, …)
31
+ * for the "Last used" hint; null when none, or the instance turned it off.
32
+ */
33
+ readonly lastMethod: WritableSignal<string>;
29
34
  /** The sign-in captcha (identifier step / `needs_captcha` challenge). */
30
35
  readonly captcha: CaptchaController;
31
36
  /** The sign-up captcha (the create-account step). */
@@ -40,6 +45,34 @@ export declare class AtlasFlowController {
40
45
  * otherwise.
41
46
  */
42
47
  readonly preparedFactor: WritableSignal<"email_code">;
48
+ /**
49
+ * "Email me a code instead" at the second factor ({@link sendEmailSecondFactor}):
50
+ * in flight, where the code went, or why it was not sent. Null until asked,
51
+ * and again once the flow leaves that step.
52
+ */
53
+ readonly emailSecondFactor: WritableSignal<{
54
+ busy?: boolean;
55
+ sentTo?: string;
56
+ error?: string;
57
+ }>;
58
+ /** "Text me a code instead" at the second factor ({@link sendSmsSecondFactor}): as {@link emailSecondFactor}. */
59
+ readonly smsSecondFactor: WritableSignal<{
60
+ busy?: boolean;
61
+ sentTo?: string;
62
+ error?: string;
63
+ }>;
64
+ /**
65
+ * The MFA enrolment step (`needs_mfa_enrollment`): the authenticator app's
66
+ * setup (QR code, setup key) or a texted code. Started and reset with the flow.
67
+ */
68
+ readonly enrollment: MfaEnrollmentController;
69
+ /** {@link enrollment}'s state, for templates. */
70
+ readonly enrollmentState: WritableSignal<MfaEnrollmentState>;
71
+ /**
72
+ * The instance's policies (terms, privacy, …) for the create-account form:
73
+ * {@link create} sends their acceptances and reloads them after a refusal.
74
+ */
75
+ readonly policies: PolicyAcceptanceController;
43
76
  private pollTimer;
44
77
  private identifier;
45
78
  constructor(client: FapiClient, reload: () => Promise<boolean>, pending: {
@@ -48,6 +81,10 @@ export declare class AtlasFlowController {
48
81
  } | null,
49
82
  /** Resolves the captcha messages' catalog keys. Defaults to en-US. */
50
83
  t?: (key: string) => string);
84
+ /** What the app lets the MFA steps offer (from {@link settings}). */
85
+ mfaChoices(): MfaChoices;
86
+ /** Start the enrolment step for its attempt, or reset it once the flow leaves. */
87
+ private syncEnrollment;
51
88
  /** Fetch the instance's public settings and draw whatever captcha they require. */
52
89
  loadSettings(): Promise<void>;
53
90
  /**
@@ -87,6 +124,10 @@ export declare class AtlasFlowController {
87
124
  * the app sees a signed-in user.
88
125
  */
89
126
  submit(values: Record<string, string>): Promise<void>;
127
+ /** Load the sign-up's policies into {@link policies} (`<atlas-sign-up>` calls it on init). */
128
+ loadPolicies(locale?: string): Promise<void>;
129
+ /** The user declined a policy a sign-in was waiting on: cancel the attempt and say why. */
130
+ declinePolicy(title: string): void;
90
131
  /**
91
132
  * Create an account (`POST /v1/client/sign_ups`) from a create-account form's
92
133
  * values — email, password and any configured sign-up fields — carrying the
@@ -94,6 +135,37 @@ export declare class AtlasFlowController {
94
135
  * then posted with {@link submit}.
95
136
  */
96
137
  create(values: Record<string, string>, consent?: boolean): Promise<void>;
138
+ /**
139
+ * "Email me a code instead" at the second factor (the instance's
140
+ * `account.emailSecondFactor`): mails a code to the account's verified email;
141
+ * it is then posted with {@link submit} like any 2FA code.
142
+ */
143
+ sendEmailSecondFactor(): Promise<void>;
144
+ /**
145
+ * "Text me a code instead" at the second factor (where the app offers texted
146
+ * codes, {@link mfaChoices}`().sms`): texts a code to the account's enrolled
147
+ * phone; it is then posted with {@link submit} like any 2FA code.
148
+ */
149
+ sendSmsSecondFactor(): Promise<void>;
150
+ private sendSecondFactorCode;
151
+ /** Resend a sign-up's emailed code / link (the earlier one stops working). */
152
+ resendSignUp(): Promise<void>;
153
+ /**
154
+ * Start a passkey-only sign-up (`POST /v1/client/sign_ups/passkey`) from the
155
+ * create-account form's values — no password. Offered when the instance's
156
+ * `account.passkeySignUp` is set.
157
+ */
158
+ createWithPasskey(values: Record<string, string>, consent?: boolean): Promise<void>;
159
+ /** The passkey-only sign-up's last step: create the passkey, and with it the account. */
160
+ createPasskey(): Promise<void>;
161
+ /**
162
+ * The recovery codes an MFA enrolment just completed the sign-in with, shown
163
+ * once before it finishes ({@link saveRecoveryCodes}); null otherwise. They
164
+ * live only in this controller's memory.
165
+ */
166
+ recoveryCodes(): string[] | null;
167
+ /** "I've saved my codes": forget the recovery codes and finish the sign-in. */
168
+ saveRecoveryCodes(): Promise<void>;
97
169
  private finish;
98
170
  /** Start/stop the §5.3 magic-link poll to match the current state. */
99
171
  syncPolling(): void;
@@ -0,0 +1,27 @@
1
+ import { EventEmitter } from '@angular/core';
2
+ import { type EndImpersonationResult } from '@atlasauth/js';
3
+ import { AtlasService } from '../atlas.service';
4
+ import { type ElementKey } from '../appearance';
5
+ import * as i0 from "@angular/core";
6
+ /**
7
+ * `<atlas-impersonation-banner>` — shown only while the active session is an
8
+ * impersonation, naming the user acted as, with "Return to admin" (or "End
9
+ * impersonation" when there is no session of the impersonator's to resume).
10
+ * Emits `ended` with the outcome. The Angular peer of React's
11
+ * `<ImpersonationBanner/>`.
12
+ */
13
+ export declare class ImpersonationBannerComponent {
14
+ protected readonly atlas: AtlasService;
15
+ readonly ended: EventEmitter<EndImpersonationResult>;
16
+ protected readonly busy: import("@angular/core").WritableSignal<boolean>;
17
+ protected readonly actor: import("@angular/core").Signal<{
18
+ sub: string;
19
+ }>;
20
+ protected readonly canReturn: import("@angular/core").Signal<boolean>;
21
+ protected readonly name: import("@angular/core").Signal<string>;
22
+ protected t(key: string, vars?: Record<string, string>): string;
23
+ protected cls(key: ElementKey, base: string): string;
24
+ protected end(): Promise<void>;
25
+ static ɵfac: i0.ɵɵFactoryDeclaration<ImpersonationBannerComponent, never>;
26
+ static ɵcmp: i0.ɵɵComponentDeclaration<ImpersonationBannerComponent, "atlas-impersonation-banner", never, {}, { "ended": "ended"; }, never, never, true, never>;
27
+ }
@@ -0,0 +1,34 @@
1
+ import { type OnDestroy, type OnInit } from '@angular/core';
2
+ import { AtlasService } from '../atlas.service';
3
+ import { type ElementKey } from '../appearance';
4
+ import type { AtlasOrganizationAuditLog } from './organization-audit-log';
5
+ import * as i0 from "@angular/core";
6
+ /**
7
+ * `<atlas-organization-audit-log>` — the active organization's audit trail for
8
+ * its admins, next to `<atlas-organization-profile>`. The Angular peer of
9
+ * React's `<OrganizationAuditLog/>`. Renders nothing for a member who may not
10
+ * read it (the server is the authority; the component just follows it). Labels
11
+ * are inputs so an app can localise them.
12
+ */
13
+ export declare class OrganizationAuditLogComponent implements OnInit, OnDestroy {
14
+ /** Entries per page (the server caps it). */
15
+ pageSize?: number;
16
+ /** Narrow to one action, or a prefix ending in `.`. */
17
+ action?: string;
18
+ labels: {
19
+ title?: string;
20
+ empty?: string;
21
+ loadMore?: string;
22
+ actor?: string;
23
+ };
24
+ formatDate: (ms: number) => string;
25
+ protected readonly atlas: AtlasService;
26
+ /** Created in ngOnInit, once the inputs are set (templates render after it). */
27
+ protected log: AtlasOrganizationAuditLog;
28
+ ngOnInit(): void;
29
+ ngOnDestroy(): void;
30
+ protected describe(action: string): string;
31
+ protected cls(key: ElementKey, base: string): string;
32
+ static ɵfac: i0.ɵɵFactoryDeclaration<OrganizationAuditLogComponent, never>;
33
+ static ɵcmp: i0.ɵɵComponentDeclaration<OrganizationAuditLogComponent, "atlas-organization-audit-log", never, { "pageSize": { "alias": "pageSize"; "required": false; }; "action": { "alias": "action"; "required": false; }; "labels": { "alias": "labels"; "required": false; }; "formatDate": { "alias": "formatDate"; "required": false; }; }, {}, never, never, true, never>;
34
+ }
@@ -0,0 +1,25 @@
1
+ import { type Signal } from '@angular/core';
2
+ import type { Observable } from 'rxjs';
3
+ import { type FapiClient, type OrganizationAuditLogOptions, type OrganizationAuditLogState } from '@atlasauth/js';
4
+ import type { AtlasOrganizationMembership } from '../types';
5
+ /**
6
+ * The active organization's audit trail, for its admins — the engine behind
7
+ * `<atlas-organization-audit-log>` and `AtlasService.organizationAuditLog()`
8
+ * (the Angular peer of React's `useOrganizationAuditLog`). `state` is a signal
9
+ * of `{ entries, loading, forbidden, hasMore }`, one page at a time, newest
10
+ * first. It follows the active organization until {@link destroy}.
11
+ */
12
+ export declare class AtlasOrganizationAuditLog {
13
+ private readonly _state;
14
+ private readonly log;
15
+ private readonly unsubscribe;
16
+ private readonly organizationSub;
17
+ readonly state: Signal<OrganizationAuditLogState>;
18
+ constructor(client: Pick<FapiClient, 'get'>, organization$: Observable<AtlasOrganizationMembership | null>, options?: OrganizationAuditLogOptions);
19
+ /** Append the next page, when there is one. */
20
+ loadMore(): Promise<void>;
21
+ /** Re-read from the newest entry. */
22
+ reload(): Promise<void>;
23
+ /** Stop following the active organization. */
24
+ destroy(): void;
25
+ }
@@ -1,16 +1,65 @@
1
+ import { EventEmitter } from '@angular/core';
2
+ import { type OrganizationProfileState } from '@atlasauth/js';
1
3
  import { AtlasService } from '../atlas.service';
2
4
  import { type ElementKey } from '../appearance';
3
5
  import * as i0 from "@angular/core";
6
+ type Tab = 'members' | 'invitations' | 'roles' | 'settings';
7
+ type ProfileRole = OrganizationProfileState['roles'][number];
4
8
  /**
5
- * `<atlas-organization-profile>` — the active organization's surface. The
6
- * Angular peer of React's `<OrganizationProfile/>`. Management controls are
7
- * gated on the ACTIVE org role via `*atlasProtect`, matching the server's rule
8
- * rather than duplicating a looser one. Renders nothing with no active org.
9
+ * `<atlas-organization-profile>` — the active organization's members (admins
10
+ * change roles and remove), invitations (admins invite, revoke and resend) and
11
+ * settings (leave; an admin deletes after confirming their password). The
12
+ * Angular peer of React's `<OrganizationProfile/>`, on the same headless
13
+ * controller. Every control is gated on the ACTIVE org role, matching the
14
+ * server's rule. Renders nothing with no active org. Emits `exit` with `left`
15
+ * or `deleted`.
9
16
  */
10
17
  export declare class OrganizationProfileComponent {
11
18
  protected readonly atlas: AtlasService;
12
- protected t(key: string): string;
19
+ readonly exit: EventEmitter<"left" | "deleted">;
20
+ private readonly client;
21
+ private controller;
22
+ private unsubscribe;
23
+ protected readonly state: import("@angular/core").WritableSignal<OrganizationProfileState>;
24
+ protected readonly tab: import("@angular/core").WritableSignal<Tab>;
25
+ protected readonly email: import("@angular/core").WritableSignal<string>;
26
+ protected readonly inviteRole: import("@angular/core").WritableSignal<string>;
27
+ protected readonly confirm: import("@angular/core").WritableSignal<"delete" | "leave">;
28
+ protected readonly needsPassword: import("@angular/core").WritableSignal<boolean>;
29
+ protected readonly password: import("@angular/core").WritableSignal<string>;
30
+ protected readonly editingRole: import("@angular/core").WritableSignal<string>;
31
+ protected readonly roleKey: import("@angular/core").WritableSignal<string>;
32
+ protected readonly roleName: import("@angular/core").WritableSignal<string>;
33
+ protected readonly rolePerms: import("@angular/core").WritableSignal<string[]>;
34
+ protected readonly customRoles: import("@angular/core").Signal<import("@atlasauth/js").OrganizationRole[]>;
35
+ protected readonly userId: import("@angular/core").Signal<string>;
36
+ protected readonly canManage: import("@angular/core").Signal<boolean>;
37
+ protected readonly isAdmin: import("@angular/core").Signal<boolean>;
38
+ protected readonly tabs: import("@angular/core").Signal<Tab[]>;
39
+ protected readonly roles: import("@angular/core").Signal<import("@atlasauth/js").OrganizationRole[] | {
40
+ key: string;
41
+ name: string;
42
+ }[]>;
43
+ protected readonly errorMessage: import("@angular/core").Signal<string>;
44
+ constructor();
45
+ private bind;
46
+ protected t(key: string, vars?: Record<string, string>): string;
13
47
  protected cls(key: ElementKey, base: string): string;
48
+ protected memberName(m: OrganizationProfileState['members'][number]): string;
49
+ protected changeRole(userId: string, role: string): void;
50
+ protected removeMember(userId: string): void;
51
+ protected sendInvite(): Promise<void>;
52
+ protected resend(id: string): void;
53
+ protected revoke(id: string): void;
54
+ protected leave(): Promise<void>;
55
+ protected remove(): Promise<void>;
56
+ protected editRole(role: ProfileRole): void;
57
+ protected resetRoleForm(): void;
58
+ protected togglePermission(key: string, on: boolean): void;
59
+ protected saveRole(): Promise<void>;
60
+ protected deleteRole(role: ProfileRole): void;
61
+ protected cancel(): void;
14
62
  static ɵfac: i0.ɵɵFactoryDeclaration<OrganizationProfileComponent, never>;
15
- static ɵcmp: i0.ɵɵComponentDeclaration<OrganizationProfileComponent, "atlas-organization-profile", never, {}, {}, never, never, true, never>;
63
+ static ɵcmp: i0.ɵɵComponentDeclaration<OrganizationProfileComponent, "atlas-organization-profile", never, {}, { "exit": "exit"; }, never, never, true, never>;
16
64
  }
65
+ export {};
@@ -0,0 +1,88 @@
1
+ import { EventEmitter, OnChanges, OnDestroy, OnInit, type SimpleChanges } from '@angular/core';
2
+ import { type PolicyAcceptanceController, type PolicyClasses, type PolicyT } from '@atlasauth/js';
3
+ import { AtlasService } from '../atlas.service';
4
+ import * as i0 from "@angular/core";
5
+ /** The policy UI's translator (the localization bundle, else the English policy strings) for the current Atlas service. */
6
+ export declare function policyUi(atlas: AtlasService): {
7
+ t: PolicyT;
8
+ classes: PolicyClasses;
9
+ };
10
+ /**
11
+ * `[atlasPolicies]="controller"` — draws the instance's policies (terms, privacy,
12
+ * …) into the host element: `kind="consent"` (default) is the checkbox block with
13
+ * its in-page viewer, `kind="clickwrap"` the "By continuing you agree to …" line.
14
+ * The state is the controller's (`AtlasFlowController.policies`); the DOM comes
15
+ * from `@atlasauth/js`, shared with every SDK.
16
+ */
17
+ export declare class AtlasPoliciesDirective implements OnInit, OnChanges, OnDestroy {
18
+ private readonly host;
19
+ private readonly atlas;
20
+ private mounted;
21
+ private ready;
22
+ controller: PolicyAcceptanceController | null;
23
+ atlasPolicyKind: 'consent' | 'clickwrap';
24
+ ngOnInit(): void;
25
+ ngOnChanges(changes: SimpleChanges): void;
26
+ ngOnDestroy(): void;
27
+ private draw;
28
+ static ɵfac: i0.ɵɵFactoryDeclaration<AtlasPoliciesDirective, never>;
29
+ static ɵdir: i0.ɵɵDirectiveDeclaration<AtlasPoliciesDirective, "[atlasPolicies]", never, { "controller": { "alias": "atlasPolicies"; "required": false; }; "atlasPolicyKind": { "alias": "atlasPolicyKind"; "required": false; }; }, {}, never, never, true, never>;
30
+ }
31
+ /**
32
+ * `<atlas-policy-accept-step>` — the sign-in step for a `needs_policy_acceptance`
33
+ * attempt: scroll-mode policies in their unskippable dialog, the rest as
34
+ * checkboxes, then "Accept and continue". Emits `submitFlow` with the
35
+ * `policy_acceptances` JSON for the flow, and `declined` with the policy title
36
+ * when the user declines (cancel the attempt).
37
+ */
38
+ export declare class PolicyAcceptStepComponent implements OnInit, OnChanges, OnDestroy {
39
+ private readonly host;
40
+ private readonly atlas;
41
+ private step;
42
+ private alive;
43
+ attempt: {
44
+ id: string | null;
45
+ pending_policies?: unknown;
46
+ } | null;
47
+ busy: boolean;
48
+ submitFlow: EventEmitter<Record<string, string>>;
49
+ declined: EventEmitter<string>;
50
+ protected readonly loading: import("@angular/core").WritableSignal<boolean>;
51
+ protected loadingText: string;
52
+ ngOnInit(): void;
53
+ ngOnChanges(changes: SimpleChanges): void;
54
+ ngOnDestroy(): void;
55
+ static ɵfac: i0.ɵɵFactoryDeclaration<PolicyAcceptStepComponent, never>;
56
+ static ɵcmp: i0.ɵɵComponentDeclaration<PolicyAcceptStepComponent, "atlas-policy-accept-step", never, { "attempt": { "alias": "attempt"; "required": false; }; "busy": { "alias": "busy"; "required": false; }; }, { "submitFlow": "submitFlow"; "declined": "declined"; }, never, never, true, never>;
57
+ }
58
+ /**
59
+ * `<atlas-policy-gate>` — in-app re-acceptance. For a signed-in user, a banner
60
+ * when a policy needs re-acceptance; "Review and accept" opens the unskippable
61
+ * dialog / checkboxes and posts `/v1/client/me/policies/accept`. Projects its
62
+ * content always.
63
+ */
64
+ export declare class PolicyGateComponent implements OnInit, OnDestroy {
65
+ private readonly host;
66
+ private readonly atlas;
67
+ private readonly ui;
68
+ private gate;
69
+ private off;
70
+ private step;
71
+ private readonly version;
72
+ accepted: EventEmitter<void>;
73
+ protected readonly reviewing: import("@angular/core").WritableSignal<boolean>;
74
+ protected readonly error: import("@angular/core").WritableSignal<string>;
75
+ protected title: string;
76
+ protected reviewText: string;
77
+ protected linkClass: string;
78
+ protected errorClass: string;
79
+ protected bannerClass: string;
80
+ protected cardClass: string;
81
+ protected bannerText(): string | null;
82
+ ngOnInit(): void;
83
+ begin(): Promise<void>;
84
+ private close;
85
+ ngOnDestroy(): void;
86
+ static ɵfac: i0.ɵɵFactoryDeclaration<PolicyGateComponent, never>;
87
+ static ɵcmp: i0.ɵɵComponentDeclaration<PolicyGateComponent, "atlas-policy-gate", never, {}, { "accepted": "accepted"; }, never, ["*"], true, never>;
88
+ }
@@ -0,0 +1,26 @@
1
+ import { EventEmitter, OnChanges } from '@angular/core';
2
+ import { type ElementKey } from '../appearance';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * The recovery codes a mid-sign-in MFA enrolment came with, shown once before
6
+ * the sign-in finishes: copy them, download them as a .txt file, then
7
+ * "I've saved my codes" (`saved`) exchanges the ticket. The codes live only in
8
+ * the flow controller's memory and are forgotten once saved.
9
+ */
10
+ export declare class RecoveryCodesComponent implements OnChanges {
11
+ private readonly atlas;
12
+ private readonly cdr;
13
+ codes: string[];
14
+ busy: boolean;
15
+ saved: EventEmitter<void>;
16
+ protected readonly canCopy: boolean;
17
+ protected readonly canDownload: boolean;
18
+ protected copied: boolean;
19
+ ngOnChanges(): void;
20
+ protected t(key: string): string;
21
+ protected cls(key: ElementKey, base: string): string;
22
+ protected copy(): void;
23
+ protected download(): void;
24
+ static ɵfac: i0.ɵɵFactoryDeclaration<RecoveryCodesComponent, never>;
25
+ static ɵcmp: i0.ɵɵComponentDeclaration<RecoveryCodesComponent, "atlas-recovery-codes", never, { "codes": { "alias": "codes"; "required": false; }; "busy": { "alias": "busy"; "required": false; }; }, { "saved": "saved"; }, never, never, true, never>;
26
+ }
@@ -22,6 +22,8 @@ export declare class SignInComponent implements OnInit, OnDestroy {
22
22
  */
23
23
  signUpUrl?: string | null;
24
24
  protected t(key: string): string;
25
+ /** "Last used: Password" on the identifier step, when the instance shows the hint. */
26
+ protected lastUsedLabel(): string | null;
25
27
  protected signUpHref(): string | null;
26
28
  protected readonly flow: AtlasFlowController;
27
29
  ngOnInit(): void;
@@ -1,5 +1,5 @@
1
- import { EventEmitter } from '@angular/core';
2
- import { type CaptchaController, type FieldError, type InstanceSettings, type PublicSignUpField } from '@atlasauth/js';
1
+ import { EventEmitter, OnChanges, OnDestroy, type SimpleChanges } from '@angular/core';
2
+ import { type PolicyAcceptanceController, type CaptchaController, type FieldError, type InstanceSettings, type PublicSignUpField } from '@atlasauth/js';
3
3
  import { type ElementKey } from '../appearance';
4
4
  import * as i0 from "@angular/core";
5
5
  /** What the create-account form emits: the values typed plus the consent tick. */
@@ -15,16 +15,32 @@ export interface SignUpFormSubmit {
15
15
  * email (`settings.emailDelivery.passwordSignUp === false`) it shows the
16
16
  * `signUp.emailUnavailable` notice instead of the form.
17
17
  */
18
- export declare class SignUpFormComponent {
18
+ export declare class SignUpFormComponent implements OnChanges, OnDestroy {
19
19
  private readonly atlas;
20
+ private readonly cdr;
21
+ private unwatch;
20
22
  settings: InstanceSettings | null;
21
23
  busy: boolean;
22
24
  errors: FieldError[];
23
25
  captcha: CaptchaController | null;
26
+ /** Passkey-only sign-up: no password field; the email per the instance's mode. */
27
+ passkey: {
28
+ email: 'off' | 'optional' | 'required';
29
+ } | null;
30
+ /** Whether the password / passkey toggle is shown (both are offered). */
31
+ switchable: boolean;
32
+ /** The instance's policies (terms, privacy, …); they replace the legacy consent row. */
33
+ policies: PolicyAcceptanceController | null;
34
+ /** The user asked for the other sign-up method. */
35
+ switchMode: EventEmitter<void>;
24
36
  /** Emits the typed values and the consent tick when the form is submitted. */
25
37
  submitSignUp: EventEmitter<SignUpFormSubmit>;
26
38
  protected values: Record<string, string>;
27
39
  protected agreed: boolean;
40
+ protected declined: string | null;
41
+ ngOnChanges(changes: SimpleChanges): void;
42
+ ngOnDestroy(): void;
43
+ protected hasPolicies(): boolean;
28
44
  protected t(key: string, vars?: Record<string, string>): string;
29
45
  /** A server error in the app's language (`error.<reason>`, else the server's message). */
30
46
  protected errorText(error: FieldError): string;
@@ -32,6 +48,8 @@ export declare class SignUpFormComponent {
32
48
  protected setValue(name: string, value: string): void;
33
49
  /** Email + password sign-up cannot complete: the app cannot send the verification email. */
34
50
  protected emailUnavailable(): boolean;
51
+ protected showEmail(): boolean;
52
+ protected emailRequired(): boolean;
35
53
  protected fields(): PublicSignUpField[];
36
54
  protected label(f: PublicSignUpField): string;
37
55
  protected inputType(f: PublicSignUpField): string;
@@ -45,5 +63,5 @@ export declare class SignUpFormComponent {
45
63
  protected fieldErrorsFor(name: string): FieldError[];
46
64
  protected onSubmit(event: Event): void;
47
65
  static ɵfac: i0.ɵɵFactoryDeclaration<SignUpFormComponent, never>;
48
- static ɵcmp: i0.ɵɵComponentDeclaration<SignUpFormComponent, "atlas-sign-up-form", never, { "settings": { "alias": "settings"; "required": false; }; "busy": { "alias": "busy"; "required": false; }; "errors": { "alias": "errors"; "required": false; }; "captcha": { "alias": "captcha"; "required": false; }; }, { "submitSignUp": "submitSignUp"; }, never, never, true, never>;
66
+ static ɵcmp: i0.ɵɵComponentDeclaration<SignUpFormComponent, "atlas-sign-up-form", never, { "settings": { "alias": "settings"; "required": false; }; "busy": { "alias": "busy"; "required": false; }; "errors": { "alias": "errors"; "required": false; }; "captcha": { "alias": "captcha"; "required": false; }; "passkey": { "alias": "passkey"; "required": false; }; "switchable": { "alias": "switchable"; "required": false; }; "policies": { "alias": "policies"; "required": false; }; }, { "switchMode": "switchMode"; "submitSignUp": "submitSignUp"; }, never, never, true, never>;
49
67
  }