@geolonia/geonicdb-sdk 0.14.0 → 0.15.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.
package/geonicdb.d.ts CHANGED
@@ -195,6 +195,13 @@ export interface LoginOptions {
195
195
  * be sender-constrained, so it is not persisted.
196
196
  */
197
197
  rememberSession?: boolean;
198
+ /**
199
+ * #1532: 管理者発行の一時パスワードで初回ログインする際に、設定する新パスワードを同梱する。
200
+ * 一時パスワードでのログインは、これを付けないとサーバが `PasswordResetRequired` (409) を
201
+ * 返す。付けると、その場で新パスワードを設定して本トークンを発行する (単発型、再ログイン不要)。
202
+ * 通常のログインでは指定しない。
203
+ */
204
+ newPassword?: string;
198
205
  }
199
206
  /** Response from the login endpoint. */
200
207
  export interface LoginResponse {
@@ -313,6 +320,20 @@ export declare class NotFoundError extends GeonicDBError {
313
320
  export declare class ConflictError extends GeonicDBError {
314
321
  constructor(message?: string);
315
322
  }
323
+ /**
324
+ * 409 — 一時パスワードでの初回ログインで、新パスワードの設定が必要 (#1532)。
325
+ * `login(email, tempPassword)` がこれを投げたら、新パスワードを集めて
326
+ * `login(email, tempPassword, { newPassword })` を呼び直す。
327
+ */
328
+ export declare class PasswordResetRequiredError extends AuthenticationError {
329
+ constructor(message?: string);
330
+ }
331
+ /**
332
+ * 403 — 一時パスワードの有効期限切れ (#1532)。管理者に再発行を依頼する。
333
+ */
334
+ export declare class TemporaryPasswordExpiredError extends AuthenticationError {
335
+ constructor(message?: string);
336
+ }
316
337
  /** 422 — Validation error (bad request payload). */
317
338
  export declare class ValidationError extends GeonicDBError {
318
339
  constructor(message?: string);
package/geonicdb.iife.js CHANGED
@@ -30,7 +30,9 @@ var GeonicDBModule = (() => {
30
30
  GeonicDBError: () => GeonicDBError,
31
31
  NetworkError: () => NetworkError,
32
32
  NotFoundError: () => NotFoundError,
33
+ PasswordResetRequiredError: () => PasswordResetRequiredError,
33
34
  RateLimitError: () => RateLimitError,
35
+ TemporaryPasswordExpiredError: () => TemporaryPasswordExpiredError,
34
36
  ValidationError: () => ValidationError,
35
37
  buildPathWithParams: () => buildPathWithParams,
36
38
  default: () => index_default
@@ -80,6 +82,7 @@ var GeonicDBModule = (() => {
80
82
  var RECONNECT_BASE_MS = 1e3;
81
83
  var RECONNECT_MAX_DELAY_MS = 3e4;
82
84
  var SUB_PROTOCOL = "access_token";
85
+ var NGSI_LD_CORE_CONTEXT = "https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context.jsonld";
83
86
  var SDK_CACHE_MAX_ENTRIES_DEFAULT = 1e3;
84
87
  var SDK_POLL_INTERVAL_MS_DEFAULT = 5e3;
85
88
  var DPOP_IDB_NAME = "geonicdb-sdk";
@@ -321,6 +324,20 @@ var GeonicDBModule = (() => {
321
324
  this.name = "ConflictError";
322
325
  }
323
326
  };
327
+ var PasswordResetRequiredError = class extends AuthenticationError {
328
+ constructor(message = "Password reset required: set a new password to complete login") {
329
+ super(message);
330
+ this.name = "PasswordResetRequiredError";
331
+ this.statusCode = 409;
332
+ }
333
+ };
334
+ var TemporaryPasswordExpiredError = class extends AuthenticationError {
335
+ constructor(message = "Temporary password expired: ask an administrator to re-issue it") {
336
+ super(message);
337
+ this.name = "TemporaryPasswordExpiredError";
338
+ this.statusCode = 403;
339
+ }
340
+ };
324
341
  var ValidationError = class extends GeonicDBError {
325
342
  constructor(message = "Validation failed") {
326
343
  super(message, 422);
@@ -711,16 +728,24 @@ var GeonicDBModule = (() => {
711
728
  "Content-Type": "application/json"
712
729
  };
713
730
  if (this._tenant) headers["NGSILD-Tenant"] = this._tenant;
731
+ const loginBody = { email, password };
732
+ if (options?.newPassword !== void 0) loginBody.newPassword = options.newPassword;
714
733
  const res = await fetch(this._baseUrl + "/auth/login", {
715
734
  method: "POST",
716
735
  headers,
717
- body: JSON.stringify({ email, password })
736
+ body: JSON.stringify(loginBody)
718
737
  });
719
738
  if (!res.ok) {
720
739
  const e = await res.json().catch(() => ({}));
721
- throw new AuthenticationError(
722
- e.detail || e.description || "Login failed: " + res.status
723
- );
740
+ const message = e.detail || e.description || "Login failed: " + res.status;
741
+ const code = e.error || e.type || e.title || "";
742
+ if (res.status === 409 && code.includes("PasswordResetRequired")) {
743
+ throw new PasswordResetRequiredError(message);
744
+ }
745
+ if (res.status === 403 && code.includes("TemporaryPasswordExpired")) {
746
+ throw new TemporaryPasswordExpiredError(message);
747
+ }
748
+ throw new AuthenticationError(message);
724
749
  }
725
750
  const data = await res.json();
726
751
  this._anonymous = false;
@@ -1221,7 +1246,15 @@ var GeonicDBModule = (() => {
1221
1246
  }
1222
1247
  const url = this._baseUrl + path;
1223
1248
  const isDPoP = this._tokenType === "DPoP" && !!this._dpopKeyPair && token !== null;
1224
- const bodyStr = body !== void 0 ? JSON.stringify(body) : void 0;
1249
+ const isEntityWrite = path.split("?")[0].startsWith("/ngsi-ld/v1/entities");
1250
+ let effectiveBody = body;
1251
+ if (isEntityWrite && effectiveBody !== null && typeof effectiveBody === "object" && !Array.isArray(effectiveBody) && !("@context" in effectiveBody)) {
1252
+ effectiveBody = {
1253
+ ...effectiveBody,
1254
+ "@context": NGSI_LD_CORE_CONTEXT
1255
+ };
1256
+ }
1257
+ const bodyStr = effectiveBody !== void 0 ? JSON.stringify(effectiveBody) : void 0;
1225
1258
  const doRequest = async (reqToken, dpopNonce) => {
1226
1259
  const reqIsDPoP = this._tokenType === "DPoP" && !!this._dpopKeyPair && reqToken !== null;
1227
1260
  const dpopProof = reqIsDPoP ? await createDPoPProof(