geoserver-node-client 1.5.2 → 1.6.1

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/README.md CHANGED
@@ -117,14 +117,14 @@ A request either succeeds or throws the custom `GeoServerResponseError`. It has
117
117
  First start a test setup using this Docker compose file:
118
118
 
119
119
  ```shell
120
- docker-compose -f test/docker-compose.yml up
120
+ GEOSERVER_VERSION=2.28.0 TEMP_DIR=/tmp/gs docker compose -f test/docker-compose.yml up
121
121
  ```
122
122
 
123
123
  Then, in an other terminal, run:
124
124
 
125
125
  ```shell
126
126
  # specify the GeoServer version and run the test suite
127
- GEOSERVER_VERSION=2.20.4 npm run test
127
+ GEOSERVER_VERSION=2.28.0 npm run test
128
128
  ```
129
129
 
130
130
  ## Release
@@ -148,7 +148,7 @@ npm login
148
148
  # then enter your credentials
149
149
  ```
150
150
 
151
- 3. Locally checkout the latest `master` branch that you would like to release, then run:
151
+ 3. Locally checkout the latest `main` branch that you would like to release, then run:
152
152
 
153
153
  ```shell
154
154
  npm run release
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geoserver-node-client",
3
- "version": "1.5.2",
3
+ "version": "1.6.1",
4
4
  "description": "Node.js client for GeoServer REST API",
5
5
  "type": "commonjs",
6
6
  "main": "geoserver-rest-client.js",
@@ -44,14 +44,14 @@
44
44
  "@babel/core": "^7.27.4",
45
45
  "@babel/plugin-transform-runtime": "^7.27.4",
46
46
  "@babel/preset-env": "^7.22.20",
47
- "@eslint/compat": "^1.2.9",
47
+ "@eslint/compat": "^2.0.0",
48
48
  "chai": "^6.0.1",
49
49
  "eslint": "^9.29.0",
50
50
  "eslint-config-prettier": "^10.1.5",
51
51
  "eslint-plugin-prettier": "^5.5.1",
52
52
  "jsdoc": "^4.0.2",
53
53
  "mocha": "^11.7.1",
54
- "neostandard": "^0.12.1",
54
+ "neostandard": "^0.13.0",
55
55
  "prettier": "^3.6.1",
56
56
  "release-it": "^19.0.3"
57
57
  }
@@ -242,26 +242,26 @@ var SecurityClient = exports["default"] = /*#__PURE__*/function () {
242
242
  return deleteUser;
243
243
  }()
244
244
  /**
245
- * Associates the given role to the user.
246
- *
247
- * @param {String} username The name of the user to add the role to
248
- * @param {String} role The role to associate
245
+ * Returns all roles registered in GeoServer.
249
246
  *
250
247
  * @throws Error if request fails
248
+ *
249
+ * @returns {Object} An object with all roles like { "roles": ["ADMIN", "GROUP_ADMIN"] }
251
250
  */
252
251
  )
253
252
  }, {
254
- key: "associateUserRole",
253
+ key: "getAllRoles",
255
254
  value: (function () {
256
- var _associateUserRole = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee5(username, role) {
257
- var response, geoServerResponse;
255
+ var _getAllRoles = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee5() {
256
+ var url, response, geoServerResponse;
258
257
  return _regenerator["default"].wrap(function (_context5) {
259
258
  while (1) switch (_context5.prev = _context5.next) {
260
259
  case 0:
260
+ url = "".concat(this.url, "security/roles.json");
261
261
  _context5.next = 1;
262
- return (0, _nodeFetch["default"])("".concat(this.url, "security/roles/role/").concat(role, "/user/").concat(username), {
262
+ return (0, _nodeFetch["default"])(url, {
263
263
  credentials: 'include',
264
- method: 'POST',
264
+ method: 'GET',
265
265
  headers: {
266
266
  Authorization: this.auth
267
267
  }
@@ -278,15 +278,330 @@ var SecurityClient = exports["default"] = /*#__PURE__*/function () {
278
278
  geoServerResponse = _context5.sent;
279
279
  throw new _geoserver.GeoServerResponseError(null, geoServerResponse);
280
280
  case 3:
281
+ return _context5.abrupt("return", response.json());
282
+ case 4:
281
283
  case "end":
282
284
  return _context5.stop();
283
285
  }
284
286
  }, _callee5, this);
285
287
  }));
286
- function associateUserRole(_x7, _x8) {
288
+ function getAllRoles() {
289
+ return _getAllRoles.apply(this, arguments);
290
+ }
291
+ return getAllRoles;
292
+ }()
293
+ /**
294
+ * Creates a new role.
295
+ *
296
+ * @param {String} role The name of the role to be created
297
+ *
298
+ * @throws Error if request fails
299
+ */
300
+ )
301
+ }, {
302
+ key: "createRole",
303
+ value: (function () {
304
+ var _createRole = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee6(role) {
305
+ var url, response, geoServerResponse, _t2;
306
+ return _regenerator["default"].wrap(function (_context6) {
307
+ while (1) switch (_context6.prev = _context6.next) {
308
+ case 0:
309
+ url = "".concat(this.url, "security/roles/role/").concat(role);
310
+ _context6.next = 1;
311
+ return (0, _nodeFetch["default"])(url, {
312
+ credentials: 'include',
313
+ method: 'POST',
314
+ headers: {
315
+ Authorization: this.auth
316
+ }
317
+ });
318
+ case 1:
319
+ response = _context6.sent;
320
+ if (response.ok) {
321
+ _context6.next = 5;
322
+ break;
323
+ }
324
+ _context6.next = 2;
325
+ return (0, _geoserver.getGeoServerResponseText)(response);
326
+ case 2:
327
+ geoServerResponse = _context6.sent;
328
+ _t2 = response.status;
329
+ _context6.next = _t2 === 404 ? 3 : 4;
330
+ break;
331
+ case 3:
332
+ throw new _geoserver.GeoServerResponseError("Role ".concat(role, " might already exist."), geoServerResponse);
333
+ case 4:
334
+ throw new _geoserver.GeoServerResponseError(null, geoServerResponse);
335
+ case 5:
336
+ case "end":
337
+ return _context6.stop();
338
+ }
339
+ }, _callee6, this);
340
+ }));
341
+ function createRole(_x7) {
342
+ return _createRole.apply(this, arguments);
343
+ }
344
+ return createRole;
345
+ }()
346
+ /**
347
+ * Deletes an existing role.
348
+ *
349
+ * @param {String} role The name of the role to be deleted
350
+ *
351
+ * @throws Error if request fails
352
+ */
353
+ )
354
+ }, {
355
+ key: "deleteRole",
356
+ value: (function () {
357
+ var _deleteRole = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee7(role) {
358
+ var url, response, geoServerResponse, _t3;
359
+ return _regenerator["default"].wrap(function (_context7) {
360
+ while (1) switch (_context7.prev = _context7.next) {
361
+ case 0:
362
+ url = "".concat(this.url, "security/roles/role/").concat(role);
363
+ _context7.next = 1;
364
+ return (0, _nodeFetch["default"])(url, {
365
+ credentials: 'include',
366
+ method: 'DELETE',
367
+ headers: {
368
+ Authorization: this.auth
369
+ }
370
+ });
371
+ case 1:
372
+ response = _context7.sent;
373
+ if (response.ok) {
374
+ _context7.next = 5;
375
+ break;
376
+ }
377
+ _context7.next = 2;
378
+ return (0, _geoserver.getGeoServerResponseText)(response);
379
+ case 2:
380
+ geoServerResponse = _context7.sent;
381
+ _t3 = response.status;
382
+ _context7.next = _t3 === 404 ? 3 : 4;
383
+ break;
384
+ case 3:
385
+ throw new _geoserver.GeoServerResponseError("Role ".concat(role, " not existing."), geoServerResponse);
386
+ case 4:
387
+ throw new _geoserver.GeoServerResponseError(null, geoServerResponse);
388
+ case 5:
389
+ case "end":
390
+ return _context7.stop();
391
+ }
392
+ }, _callee7, this);
393
+ }));
394
+ function deleteRole(_x8) {
395
+ return _deleteRole.apply(this, arguments);
396
+ }
397
+ return deleteRole;
398
+ }()
399
+ /**
400
+ * Associates the given role to the user.
401
+ *
402
+ * @param {String} username The name of the user to add the role to
403
+ * @param {String} role The role to associate
404
+ *
405
+ * @throws Error if request fails
406
+ */
407
+ )
408
+ }, {
409
+ key: "associateUserRole",
410
+ value: (function () {
411
+ var _associateUserRole = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee8(username, role) {
412
+ var response, geoServerResponse;
413
+ return _regenerator["default"].wrap(function (_context8) {
414
+ while (1) switch (_context8.prev = _context8.next) {
415
+ case 0:
416
+ _context8.next = 1;
417
+ return (0, _nodeFetch["default"])("".concat(this.url, "security/roles/role/").concat(role, "/user/").concat(username), {
418
+ credentials: 'include',
419
+ method: 'POST',
420
+ headers: {
421
+ Authorization: this.auth
422
+ }
423
+ });
424
+ case 1:
425
+ response = _context8.sent;
426
+ if (response.ok) {
427
+ _context8.next = 3;
428
+ break;
429
+ }
430
+ _context8.next = 2;
431
+ return (0, _geoserver.getGeoServerResponseText)(response);
432
+ case 2:
433
+ geoServerResponse = _context8.sent;
434
+ throw new _geoserver.GeoServerResponseError(null, geoServerResponse);
435
+ case 3:
436
+ case "end":
437
+ return _context8.stop();
438
+ }
439
+ }, _callee8, this);
440
+ }));
441
+ function associateUserRole(_x9, _x0) {
287
442
  return _associateUserRole.apply(this, arguments);
288
443
  }
289
444
  return associateUserRole;
445
+ }()
446
+ /**
447
+ * Returns all data access rules registered in GeoServer.
448
+ *
449
+ * @throws Error if request fails
450
+ *
451
+ * @returns {Object} An object with all data access rules like { "*.*.r": ["ADMIN", "GROUP_ADMIN"] }
452
+ */
453
+ )
454
+ }, {
455
+ key: "getAllAccessRules",
456
+ value: (function () {
457
+ var _getAllAccessRules = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee9() {
458
+ var url, response, geoServerResponse;
459
+ return _regenerator["default"].wrap(function (_context9) {
460
+ while (1) switch (_context9.prev = _context9.next) {
461
+ case 0:
462
+ url = "".concat(this.url, "security/acl/layers.json");
463
+ _context9.next = 1;
464
+ return (0, _nodeFetch["default"])(url, {
465
+ credentials: 'include',
466
+ method: 'GET',
467
+ headers: {
468
+ Authorization: this.auth
469
+ }
470
+ });
471
+ case 1:
472
+ response = _context9.sent;
473
+ if (response.ok) {
474
+ _context9.next = 3;
475
+ break;
476
+ }
477
+ _context9.next = 2;
478
+ return (0, _geoserver.getGeoServerResponseText)(response);
479
+ case 2:
480
+ geoServerResponse = _context9.sent;
481
+ throw new _geoserver.GeoServerResponseError(null, geoServerResponse);
482
+ case 3:
483
+ return _context9.abrupt("return", response.json());
484
+ case 4:
485
+ case "end":
486
+ return _context9.stop();
487
+ }
488
+ }, _callee9, this);
489
+ }));
490
+ function getAllAccessRules() {
491
+ return _getAllAccessRules.apply(this, arguments);
492
+ }
493
+ return getAllAccessRules;
494
+ }()
495
+ /**
496
+ * Creates a new data access rule.
497
+ *
498
+ * @param {String} rule The rule in the form '<MY_WS>.<MY_LAYER>.r'
499
+ * @param {String[]} roles The roles to allow access to rule
500
+ *
501
+ * @throws Error if request fails
502
+ */
503
+ )
504
+ }, {
505
+ key: "createDataAccessRule",
506
+ value: (function () {
507
+ var _createDataAccessRule = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee0(rule, roles) {
508
+ var url, body, response, geoServerResponse, _t4;
509
+ return _regenerator["default"].wrap(function (_context0) {
510
+ while (1) switch (_context0.prev = _context0.next) {
511
+ case 0:
512
+ url = "".concat(this.url, "security/acl/layers");
513
+ body = {};
514
+ body[rule] = roles.join(',');
515
+ _context0.next = 1;
516
+ return (0, _nodeFetch["default"])(url, {
517
+ credentials: 'include',
518
+ method: 'POST',
519
+ headers: {
520
+ Authorization: this.auth,
521
+ 'Content-Type': 'application/json'
522
+ },
523
+ body: JSON.stringify(body)
524
+ });
525
+ case 1:
526
+ response = _context0.sent;
527
+ if (response.ok) {
528
+ _context0.next = 5;
529
+ break;
530
+ }
531
+ _context0.next = 2;
532
+ return (0, _geoserver.getGeoServerResponseText)(response);
533
+ case 2:
534
+ geoServerResponse = _context0.sent;
535
+ _t4 = response.status;
536
+ _context0.next = _t4 === 404 ? 3 : 4;
537
+ break;
538
+ case 3:
539
+ throw new _geoserver.GeoServerResponseError("Rule ".concat(rule, " might already exists."), geoServerResponse);
540
+ case 4:
541
+ throw new _geoserver.GeoServerResponseError(null, geoServerResponse);
542
+ case 5:
543
+ case "end":
544
+ return _context0.stop();
545
+ }
546
+ }, _callee0, this);
547
+ }));
548
+ function createDataAccessRule(_x1, _x10) {
549
+ return _createDataAccessRule.apply(this, arguments);
550
+ }
551
+ return createDataAccessRule;
552
+ }()
553
+ /**
554
+ * Deletes an existing data access rule.
555
+ *
556
+ * @param {String} rule The rule to be deleted, like '<MY_WS>.<MY_LAYER>.r'
557
+ *
558
+ * @throws Error if request fails
559
+ */
560
+ )
561
+ }, {
562
+ key: "deleteDataAccessRule",
563
+ value: (function () {
564
+ var _deleteDataAccessRule = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee1(rule) {
565
+ var url, response, geoServerResponse, _t5;
566
+ return _regenerator["default"].wrap(function (_context1) {
567
+ while (1) switch (_context1.prev = _context1.next) {
568
+ case 0:
569
+ url = "".concat(this.url, "security/acl/layers/").concat(rule);
570
+ _context1.next = 1;
571
+ return (0, _nodeFetch["default"])(url, {
572
+ credentials: 'include',
573
+ method: 'DELETE',
574
+ headers: {
575
+ Authorization: this.auth
576
+ }
577
+ });
578
+ case 1:
579
+ response = _context1.sent;
580
+ if (response.ok) {
581
+ _context1.next = 5;
582
+ break;
583
+ }
584
+ _context1.next = 2;
585
+ return (0, _geoserver.getGeoServerResponseText)(response);
586
+ case 2:
587
+ geoServerResponse = _context1.sent;
588
+ _t5 = response.status;
589
+ _context1.next = _t5 === 404 ? 3 : 4;
590
+ break;
591
+ case 3:
592
+ throw new _geoserver.GeoServerResponseError("Rule ".concat(rule, " not existing."), geoServerResponse);
593
+ case 4:
594
+ throw new _geoserver.GeoServerResponseError(null, geoServerResponse);
595
+ case 5:
596
+ case "end":
597
+ return _context1.stop();
598
+ }
599
+ }, _callee1, this);
600
+ }));
601
+ function deleteDataAccessRule(_x11) {
602
+ return _deleteDataAccessRule.apply(this, arguments);
603
+ }
604
+ return deleteDataAccessRule;
290
605
  }())
291
606
  }]);
292
607
  }();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geoserver-node-client",
3
- "version": "1.5.2",
3
+ "version": "1.6.1",
4
4
  "description": "Node.js client for GeoServer REST API",
5
5
  "type": "module",
6
6
  "main": "geoserver-rest-client.js",
@@ -44,14 +44,14 @@
44
44
  "@babel/core": "^7.27.4",
45
45
  "@babel/plugin-transform-runtime": "^7.27.4",
46
46
  "@babel/preset-env": "^7.22.20",
47
- "@eslint/compat": "^1.2.9",
47
+ "@eslint/compat": "^2.0.0",
48
48
  "chai": "^6.0.1",
49
49
  "eslint": "^9.29.0",
50
50
  "eslint-config-prettier": "^10.1.5",
51
51
  "eslint-plugin-prettier": "^5.5.1",
52
52
  "jsdoc": "^4.0.2",
53
53
  "mocha": "^11.7.1",
54
- "neostandard": "^0.12.1",
54
+ "neostandard": "^0.13.0",
55
55
  "prettier": "^3.6.1",
56
56
  "release-it": "^19.0.3"
57
57
  }
package/src/security.js CHANGED
@@ -138,6 +138,89 @@ export default class SecurityClient {
138
138
  }
139
139
  }
140
140
 
141
+ /**
142
+ * Returns all roles registered in GeoServer.
143
+ *
144
+ * @throws Error if request fails
145
+ *
146
+ * @returns {Object} An object with all roles like { "roles": ["ADMIN", "GROUP_ADMIN"] }
147
+ */
148
+ async getAllRoles() {
149
+ const url = `${this.url}security/roles.json`;
150
+
151
+ const response = await fetch(url, {
152
+ credentials: 'include',
153
+ method: 'GET',
154
+ headers: {
155
+ Authorization: this.auth
156
+ }
157
+ });
158
+
159
+ if (!response.ok) {
160
+ const geoServerResponse = await getGeoServerResponseText(response);
161
+ throw new GeoServerResponseError(null, geoServerResponse);
162
+ }
163
+ return response.json();
164
+ }
165
+
166
+ /**
167
+ * Creates a new role.
168
+ *
169
+ * @param {String} role The name of the role to be created
170
+ *
171
+ * @throws Error if request fails
172
+ */
173
+ async createRole(role) {
174
+ const url = `${this.url}security/roles/role/${role}`;
175
+
176
+ const response = await fetch(url, {
177
+ credentials: 'include',
178
+ method: 'POST',
179
+ headers: {
180
+ Authorization: this.auth
181
+ }
182
+ });
183
+
184
+ if (!response.ok) {
185
+ const geoServerResponse = await getGeoServerResponseText(response);
186
+ switch (response.status) {
187
+ case 404:
188
+ throw new GeoServerResponseError(`Role ${role} might already exist.`, geoServerResponse);
189
+ default:
190
+ throw new GeoServerResponseError(null, geoServerResponse);
191
+ }
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Deletes an existing role.
197
+ *
198
+ * @param {String} role The name of the role to be deleted
199
+ *
200
+ * @throws Error if request fails
201
+ */
202
+ async deleteRole(role) {
203
+ const url = `${this.url}security/roles/role/${role}`;
204
+
205
+ const response = await fetch(url, {
206
+ credentials: 'include',
207
+ method: 'DELETE',
208
+ headers: {
209
+ Authorization: this.auth
210
+ }
211
+ });
212
+
213
+ if (!response.ok) {
214
+ const geoServerResponse = await getGeoServerResponseText(response);
215
+ switch (response.status) {
216
+ case 404:
217
+ throw new GeoServerResponseError(`Role ${role} not existing.`, geoServerResponse);
218
+ default:
219
+ throw new GeoServerResponseError(null, geoServerResponse);
220
+ }
221
+ }
222
+ }
223
+
141
224
  /**
142
225
  * Associates the given role to the user.
143
226
  *
@@ -160,4 +243,92 @@ export default class SecurityClient {
160
243
  throw new GeoServerResponseError(null, geoServerResponse);
161
244
  }
162
245
  }
246
+
247
+ /**
248
+ * Returns all data access rules registered in GeoServer.
249
+ *
250
+ * @throws Error if request fails
251
+ *
252
+ * @returns {Object} An object with all data access rules like { "*.*.r": ["ADMIN", "GROUP_ADMIN"] }
253
+ */
254
+ async getAllAccessRules() {
255
+ const url = `${this.url}security/acl/layers.json`;
256
+
257
+ const response = await fetch(url, {
258
+ credentials: 'include',
259
+ method: 'GET',
260
+ headers: {
261
+ Authorization: this.auth
262
+ }
263
+ });
264
+
265
+ if (!response.ok) {
266
+ const geoServerResponse = await getGeoServerResponseText(response);
267
+ throw new GeoServerResponseError(null, geoServerResponse);
268
+ }
269
+ return response.json();
270
+ }
271
+
272
+ /**
273
+ * Creates a new data access rule.
274
+ *
275
+ * @param {String} rule The rule in the form '<MY_WS>.<MY_LAYER>.r'
276
+ * @param {String[]} roles The roles to allow access to rule
277
+ *
278
+ * @throws Error if request fails
279
+ */
280
+ async createDataAccessRule(rule, roles) {
281
+ const url = `${this.url}security/acl/layers`;
282
+ const body = {};
283
+ body[rule] = roles.join(',');
284
+
285
+ const response = await fetch(url, {
286
+ credentials: 'include',
287
+ method: 'POST',
288
+ headers: {
289
+ Authorization: this.auth,
290
+ 'Content-Type': 'application/json'
291
+ },
292
+ body: JSON.stringify(body)
293
+ });
294
+
295
+ if (!response.ok) {
296
+ const geoServerResponse = await getGeoServerResponseText(response);
297
+ switch (response.status) {
298
+ case 404:
299
+ throw new GeoServerResponseError(`Rule ${rule} might already exists.`, geoServerResponse);
300
+ default:
301
+ throw new GeoServerResponseError(null, geoServerResponse);
302
+ }
303
+ }
304
+ }
305
+
306
+ /**
307
+ * Deletes an existing data access rule.
308
+ *
309
+ * @param {String} rule The rule to be deleted, like '<MY_WS>.<MY_LAYER>.r'
310
+ *
311
+ * @throws Error if request fails
312
+ */
313
+ async deleteDataAccessRule(rule) {
314
+ const url = `${this.url}security/acl/layers/${rule}`;
315
+
316
+ const response = await fetch(url, {
317
+ credentials: 'include',
318
+ method: 'DELETE',
319
+ headers: {
320
+ Authorization: this.auth
321
+ }
322
+ });
323
+
324
+ if (!response.ok) {
325
+ const geoServerResponse = await getGeoServerResponseText(response);
326
+ switch (response.status) {
327
+ case 404:
328
+ throw new GeoServerResponseError(`Rule ${rule} not existing.`, geoServerResponse);
329
+ default:
330
+ throw new GeoServerResponseError(null, geoServerResponse);
331
+ }
332
+ }
333
+ }
163
334
  }