@truenas/api-client 10.0.0 → 11.0.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.
@@ -2200,6 +2200,7 @@ var TrueNasAuthMechanism = /* @__PURE__ */ ((TrueNasAuthMechanism2) => {
2200
2200
  var AuthErrorCode = /* @__PURE__ */ ((AuthErrorCode2) => {
2201
2201
  AuthErrorCode2["PasswordAuthFailed"] = "PASSWORD_AUTH_FAILED";
2202
2202
  AuthErrorCode2["OtpAuthFailed"] = "OTP_AUTH_FAILED";
2203
+ AuthErrorCode2["OtpLoginNotPending"] = "OTP_LOGIN_NOT_PENDING";
2203
2204
  AuthErrorCode2["ApiKeyAuthFailed"] = "API_KEY_AUTH_FAILED";
2204
2205
  AuthErrorCode2["TokenAuthFailed"] = "TOKEN_AUTH_FAILED";
2205
2206
  AuthErrorCode2["LoginSuperseded"] = "LOGIN_SUPERSEDED";
@@ -2213,11 +2214,12 @@ var AuthError = class _AuthError extends Error {
2213
2214
  * `AUTH_ERR`; the code alone says only which mechanism failed. Absent when the login
2214
2215
  * never got an answer of that kind (an error frame, or a superseded login).
2215
2216
  */
2216
- constructor(code, message, response) {
2217
+ constructor(code, message, response, options = {}) {
2217
2218
  super(message);
2218
2219
  this.code = code;
2219
2220
  this.response = response;
2220
2221
  this.name = "AuthError";
2222
+ this.loginPending = options.loginPending ?? false;
2221
2223
  Object.setPrototypeOf(this, _AuthError.prototype);
2222
2224
  }
2223
2225
  };
@@ -2758,6 +2760,7 @@ var throwOnAuthenticationFailure = (code, message) => switchMap((response) => {
2758
2760
  }
2759
2761
  return of(response);
2760
2762
  });
2763
+ var isOtpLoginNotPending = (error) => error.data?.errname === "EINVAL" && typeof error.data.reason === "string" && error.data.reason.includes("OTP_TOKEN: no authentication in progress");
2761
2764
  var TrueNasAuthenticator = class _TrueNasAuthenticator {
2762
2765
  constructor(connection, version) {
2763
2766
  this.connection = connection;
@@ -2941,6 +2944,19 @@ var TrueNasAuthenticator = class _TrueNasAuthenticator {
2941
2944
  take(1)
2942
2945
  );
2943
2946
  }
2947
+ /**
2948
+ * The second step of a two-factor login, after `loginWithUserPass` answered
2949
+ * `OTP_REQUIRED`.
2950
+ *
2951
+ * Emits the answer when the code is accepted (`SUCCESS`), or when middleware
2952
+ * refuses the account outright (`EXPIRED`, `DENIED`, `REDIRECT`); never
2953
+ * `OTP_REQUIRED`. A refused code errors with `AuthError`, the same way on
2954
+ * every release:
2955
+ *
2956
+ * - `OtpAuthFailed` with `loginPending: true`: ask for another code.
2957
+ * - `OtpAuthFailed` with `loginPending: false`: start over with the password.
2958
+ * - `OtpLoginNotPending`: no login was waiting for a code; start over.
2959
+ */
2944
2960
  loginWithOtp(code) {
2945
2961
  const { sentDuring, callerInitiated } = this.beginLogin();
2946
2962
  let answered = false;
@@ -2960,6 +2976,12 @@ var TrueNasAuthenticator = class _TrueNasAuthenticator {
2960
2976
  }),
2961
2977
  map((msg) => {
2962
2978
  if (msg.error) {
2979
+ if (isOtpLoginNotPending(msg.error)) {
2980
+ throw new AuthError(
2981
+ "OTP_LOGIN_NOT_PENDING" /* OtpLoginNotPending */,
2982
+ "TrueNAS is no longer waiting for a one-time passcode for this login. Please sign in with your password again."
2983
+ );
2984
+ }
2963
2985
  const errorMessage = getApiErrorMessage(
2964
2986
  msg.error,
2965
2987
  "Authentication failed"
@@ -2968,6 +2990,23 @@ var TrueNasAuthenticator = class _TrueNasAuthenticator {
2968
2990
  }
2969
2991
  return msg.result;
2970
2992
  }),
2993
+ // A wrong code is answered differently by release, and the API version
2994
+ // does not say which: 25.10 answers `OTP_REQUIRED` and keeps the login
2995
+ // for another code, 27+ answers `AUTH_ERR` and drops it. Both are the
2996
+ // same failure to the caller, told apart only by `loginPending`, so no
2997
+ // caller has to read `OTP_REQUIRED` as "wrong code".
2998
+ map((res) => {
2999
+ const loginPending = res?.response_type === "OTP_REQUIRED" /* OtpRequired */;
3000
+ if (loginPending || res?.response_type === "AUTH_ERR" /* AuthErr */) {
3001
+ throw new AuthError(
3002
+ "OTP_AUTH_FAILED" /* OtpAuthFailed */,
3003
+ loginPending ? "TrueNAS rejected the one-time passcode. Please verify it and try again." : "TrueNAS rejected the one-time passcode. Please sign in with your password again.",
3004
+ res,
3005
+ { loginPending }
3006
+ );
3007
+ }
3008
+ return res;
3009
+ }),
2971
3010
  tap((res) => {
2972
3011
  if (res?.response_type === "SUCCESS" /* Success */) {
2973
3012
  this.assertNotSuperseded(sentDuring);
@@ -2975,10 +3014,6 @@ var TrueNasAuthenticator = class _TrueNasAuthenticator {
2975
3014
  this.authenticated$.next(true);
2976
3015
  }
2977
3016
  }),
2978
- throwOnAuthenticationFailure(
2979
- "OTP_AUTH_FAILED" /* OtpAuthFailed */,
2980
- "TrueNAS authentication failed. Please verify your one-time passcode and try again."
2981
- ),
2982
3017
  finalize(() => {
2983
3018
  this.endLogin(sentDuring, callerInitiated, answered);
2984
3019
  }),
@@ -4800,5 +4835,5 @@ var UserRole = /* @__PURE__ */ ((UserRole2) => {
4800
4835
  })(UserRole || {});
4801
4836
 
4802
4837
  export { AppState, AuthError, AuthErrorCode, AuthResponseType, InvalidVersionResponseError, JobState, NoCompatibleVersionsError, SUPPORTED_API_VERSIONS, TrueNasApiClient, TrueNasApiClientV2510, TrueNasApiClientV27, TrueNasApiClientV28, TrueNasApiError, TrueNasAuthMechanism, TrueNasAuthenticator, TrueNasConnection, UserRole, VersionCompatibility, VersionDiscovery, VersionDiscoveryError, VersionDiscoveryNetworkError, VersionDiscoveryTimeoutError, VersionEndpointNotFoundError, VersionTooNewError, VersionTooOldError, clientClassFor, consoleLogger, createTrueNasClient, getApiErrorMessage, getCloseMessage, isJobFinished, noopLogger, parseApiVersion, policyViolationCloseCode, subscriptionName, v25_10_0_exports, v25_10_1_exports, v25_10_2_exports, v25_10_3_exports, v25_10_4_exports, v25_10_5_exports, v27_0_0_exports, v28_0_0_exports };
4803
- //# sourceMappingURL=chunk-Z5U5ZRKJ.js.map
4804
- //# sourceMappingURL=chunk-Z5U5ZRKJ.js.map
4838
+ //# sourceMappingURL=chunk-ZH75OPDH.js.map
4839
+ //# sourceMappingURL=chunk-ZH75OPDH.js.map