@backstage/backend-app-api 0.6.3-next.0 → 0.7.0-next.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/CHANGELOG.md +32 -0
- package/alpha/package.json +1 -1
- package/dist/index.cjs.js +823 -253
- package/dist/index.cjs.js.map +1 -1
- package/migrations/20240327104803_public_keys.js +50 -0
- package/package.json +17 -12
package/dist/index.cjs.js
CHANGED
|
@@ -22,13 +22,15 @@ var winston = require('winston');
|
|
|
22
22
|
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
23
23
|
var alpha = require('@backstage/backend-plugin-api/alpha');
|
|
24
24
|
var jose = require('jose');
|
|
25
|
+
var pluginAuthNode = require('@backstage/plugin-auth-node');
|
|
26
|
+
var uuid = require('uuid');
|
|
27
|
+
var luxon = require('luxon');
|
|
25
28
|
var backendCommon = require('@backstage/backend-common');
|
|
26
29
|
var backendAppApi = require('@backstage/backend-app-api');
|
|
27
30
|
var cookie = require('cookie');
|
|
28
|
-
var
|
|
31
|
+
var Router = require('express-promise-router');
|
|
29
32
|
var types = require('@backstage/types');
|
|
30
33
|
var pathToRegexp = require('path-to-regexp');
|
|
31
|
-
var pluginAuthNode = require('@backstage/plugin-auth-node');
|
|
32
34
|
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
33
35
|
var express = require('express');
|
|
34
36
|
var trimEnd = require('lodash/trimEnd');
|
|
@@ -64,22 +66,22 @@ var cors__default = /*#__PURE__*/_interopDefaultCompat(cors);
|
|
|
64
66
|
var helmet__default = /*#__PURE__*/_interopDefaultCompat(helmet);
|
|
65
67
|
var morgan__default = /*#__PURE__*/_interopDefaultCompat(morgan);
|
|
66
68
|
var compression__default = /*#__PURE__*/_interopDefaultCompat(compression);
|
|
67
|
-
var
|
|
69
|
+
var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
|
|
68
70
|
var express__default = /*#__PURE__*/_interopDefaultCompat(express);
|
|
69
71
|
var trimEnd__default = /*#__PURE__*/_interopDefaultCompat(trimEnd);
|
|
70
72
|
|
|
71
|
-
var __defProp = Object.defineProperty;
|
|
72
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
73
|
-
var __publicField = (obj, key, value) => {
|
|
74
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
73
|
+
var __defProp$1 = Object.defineProperty;
|
|
74
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
75
|
+
var __publicField$1 = (obj, key, value) => {
|
|
76
|
+
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
75
77
|
return value;
|
|
76
78
|
};
|
|
77
79
|
class ObservableConfigProxy {
|
|
78
80
|
constructor(parent, parentKey) {
|
|
79
81
|
this.parent = parent;
|
|
80
82
|
this.parentKey = parentKey;
|
|
81
|
-
__publicField(this, "config", new config.ConfigReader({}));
|
|
82
|
-
__publicField(this, "subscribers", []);
|
|
83
|
+
__publicField$1(this, "config", new config.ConfigReader({}));
|
|
84
|
+
__publicField$1(this, "subscribers", []);
|
|
83
85
|
if (parent && !parentKey) {
|
|
84
86
|
throw new Error("parentKey is required if parent is set");
|
|
85
87
|
}
|
|
@@ -610,31 +612,31 @@ function applyInternalErrorFilter(error, logger) {
|
|
|
610
612
|
return error;
|
|
611
613
|
}
|
|
612
614
|
|
|
613
|
-
var __accessCheck$
|
|
615
|
+
var __accessCheck$c = (obj, member, msg) => {
|
|
614
616
|
if (!member.has(obj))
|
|
615
617
|
throw TypeError("Cannot " + msg);
|
|
616
618
|
};
|
|
617
|
-
var __privateGet$
|
|
618
|
-
__accessCheck$
|
|
619
|
+
var __privateGet$b = (obj, member, getter) => {
|
|
620
|
+
__accessCheck$c(obj, member, "read from private field");
|
|
619
621
|
return getter ? getter.call(obj) : member.get(obj);
|
|
620
622
|
};
|
|
621
|
-
var __privateAdd$
|
|
623
|
+
var __privateAdd$c = (obj, member, value) => {
|
|
622
624
|
if (member.has(obj))
|
|
623
625
|
throw TypeError("Cannot add the same private member more than once");
|
|
624
626
|
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
625
627
|
};
|
|
626
|
-
var __privateSet$
|
|
627
|
-
__accessCheck$
|
|
628
|
+
var __privateSet$b = (obj, member, value, setter) => {
|
|
629
|
+
__accessCheck$c(obj, member, "write to private field");
|
|
628
630
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
629
631
|
return value;
|
|
630
632
|
};
|
|
631
633
|
var _config, _logger;
|
|
632
634
|
const _MiddlewareFactory = class _MiddlewareFactory {
|
|
633
635
|
constructor(options) {
|
|
634
|
-
__privateAdd$
|
|
635
|
-
__privateAdd$
|
|
636
|
-
__privateSet$
|
|
637
|
-
__privateSet$
|
|
636
|
+
__privateAdd$c(this, _config, void 0);
|
|
637
|
+
__privateAdd$c(this, _logger, void 0);
|
|
638
|
+
__privateSet$b(this, _config, options.config);
|
|
639
|
+
__privateSet$b(this, _logger, options.logger);
|
|
638
640
|
}
|
|
639
641
|
/**
|
|
640
642
|
* Creates a new {@link MiddlewareFactory}.
|
|
@@ -680,7 +682,7 @@ const _MiddlewareFactory = class _MiddlewareFactory {
|
|
|
680
682
|
* @returns An Express request handler
|
|
681
683
|
*/
|
|
682
684
|
logging() {
|
|
683
|
-
const logger = __privateGet$
|
|
685
|
+
const logger = __privateGet$b(this, _logger).child({
|
|
684
686
|
type: "incomingRequest"
|
|
685
687
|
});
|
|
686
688
|
return morgan__default.default("combined", {
|
|
@@ -704,7 +706,7 @@ const _MiddlewareFactory = class _MiddlewareFactory {
|
|
|
704
706
|
* @returns An Express request handler
|
|
705
707
|
*/
|
|
706
708
|
helmet() {
|
|
707
|
-
return helmet__default.default(readHelmetOptions(__privateGet$
|
|
709
|
+
return helmet__default.default(readHelmetOptions(__privateGet$b(this, _config).getOptionalConfig("backend")));
|
|
708
710
|
}
|
|
709
711
|
/**
|
|
710
712
|
* Returns a middleware that implements the cors library.
|
|
@@ -719,7 +721,7 @@ const _MiddlewareFactory = class _MiddlewareFactory {
|
|
|
719
721
|
* @returns An Express request handler
|
|
720
722
|
*/
|
|
721
723
|
cors() {
|
|
722
|
-
return cors__default.default(readCorsOptions(__privateGet$
|
|
724
|
+
return cors__default.default(readCorsOptions(__privateGet$b(this, _config).getOptionalConfig("backend")));
|
|
723
725
|
}
|
|
724
726
|
/**
|
|
725
727
|
* Express middleware to handle errors during request processing.
|
|
@@ -744,7 +746,7 @@ const _MiddlewareFactory = class _MiddlewareFactory {
|
|
|
744
746
|
error(options = {}) {
|
|
745
747
|
var _a;
|
|
746
748
|
const showStackTraces = (_a = options.showStackTraces) != null ? _a : process.env.NODE_ENV === "development";
|
|
747
|
-
const logger = __privateGet$
|
|
749
|
+
const logger = __privateGet$b(this, _logger).child({
|
|
748
750
|
type: "errorHandler"
|
|
749
751
|
});
|
|
750
752
|
return (rawError, req, res, next) => {
|
|
@@ -803,31 +805,31 @@ const escapeRegExp = (text) => {
|
|
|
803
805
|
return text.replace(/[.*+?^${}(\)|[\]\\]/g, "\\$&");
|
|
804
806
|
};
|
|
805
807
|
|
|
806
|
-
var __accessCheck$
|
|
808
|
+
var __accessCheck$b = (obj, member, msg) => {
|
|
807
809
|
if (!member.has(obj))
|
|
808
810
|
throw TypeError("Cannot " + msg);
|
|
809
811
|
};
|
|
810
|
-
var __privateGet$
|
|
811
|
-
__accessCheck$
|
|
812
|
+
var __privateGet$a = (obj, member, getter) => {
|
|
813
|
+
__accessCheck$b(obj, member, "read from private field");
|
|
812
814
|
return getter ? getter.call(obj) : member.get(obj);
|
|
813
815
|
};
|
|
814
|
-
var __privateAdd$
|
|
816
|
+
var __privateAdd$b = (obj, member, value) => {
|
|
815
817
|
if (member.has(obj))
|
|
816
818
|
throw TypeError("Cannot add the same private member more than once");
|
|
817
819
|
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
818
820
|
};
|
|
819
|
-
var __privateSet$
|
|
820
|
-
__accessCheck$
|
|
821
|
+
var __privateSet$a = (obj, member, value, setter) => {
|
|
822
|
+
__accessCheck$b(obj, member, "write to private field");
|
|
821
823
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
822
824
|
return value;
|
|
823
825
|
};
|
|
824
826
|
var _winston, _addRedactions;
|
|
825
827
|
const _WinstonLogger = class _WinstonLogger {
|
|
826
828
|
constructor(winston, addRedactions) {
|
|
827
|
-
__privateAdd$
|
|
828
|
-
__privateAdd$
|
|
829
|
-
__privateSet$
|
|
830
|
-
__privateSet$
|
|
829
|
+
__privateAdd$b(this, _winston, void 0);
|
|
830
|
+
__privateAdd$b(this, _addRedactions, void 0);
|
|
831
|
+
__privateSet$a(this, _winston, winston);
|
|
832
|
+
__privateSet$a(this, _addRedactions, addRedactions);
|
|
831
833
|
}
|
|
832
834
|
/**
|
|
833
835
|
* Creates a {@link WinstonLogger} instance.
|
|
@@ -912,44 +914,44 @@ const _WinstonLogger = class _WinstonLogger {
|
|
|
912
914
|
);
|
|
913
915
|
}
|
|
914
916
|
error(message, meta) {
|
|
915
|
-
__privateGet$
|
|
917
|
+
__privateGet$a(this, _winston).error(message, meta);
|
|
916
918
|
}
|
|
917
919
|
warn(message, meta) {
|
|
918
|
-
__privateGet$
|
|
920
|
+
__privateGet$a(this, _winston).warn(message, meta);
|
|
919
921
|
}
|
|
920
922
|
info(message, meta) {
|
|
921
|
-
__privateGet$
|
|
923
|
+
__privateGet$a(this, _winston).info(message, meta);
|
|
922
924
|
}
|
|
923
925
|
debug(message, meta) {
|
|
924
|
-
__privateGet$
|
|
926
|
+
__privateGet$a(this, _winston).debug(message, meta);
|
|
925
927
|
}
|
|
926
928
|
child(meta) {
|
|
927
|
-
return new _WinstonLogger(__privateGet$
|
|
929
|
+
return new _WinstonLogger(__privateGet$a(this, _winston).child(meta));
|
|
928
930
|
}
|
|
929
931
|
addRedactions(redactions) {
|
|
930
932
|
var _a;
|
|
931
|
-
(_a = __privateGet$
|
|
933
|
+
(_a = __privateGet$a(this, _addRedactions)) == null ? void 0 : _a.call(this, redactions);
|
|
932
934
|
}
|
|
933
935
|
};
|
|
934
936
|
_winston = new WeakMap();
|
|
935
937
|
_addRedactions = new WeakMap();
|
|
936
938
|
let WinstonLogger = _WinstonLogger;
|
|
937
939
|
|
|
938
|
-
var __accessCheck$
|
|
940
|
+
var __accessCheck$a = (obj, member, msg) => {
|
|
939
941
|
if (!member.has(obj))
|
|
940
942
|
throw TypeError("Cannot " + msg);
|
|
941
943
|
};
|
|
942
|
-
var __privateGet$
|
|
943
|
-
__accessCheck$
|
|
944
|
+
var __privateGet$9 = (obj, member, getter) => {
|
|
945
|
+
__accessCheck$a(obj, member, "read from private field");
|
|
944
946
|
return getter ? getter.call(obj) : member.get(obj);
|
|
945
947
|
};
|
|
946
|
-
var __privateAdd$
|
|
948
|
+
var __privateAdd$a = (obj, member, value) => {
|
|
947
949
|
if (member.has(obj))
|
|
948
950
|
throw TypeError("Cannot add the same private member more than once");
|
|
949
951
|
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
950
952
|
};
|
|
951
|
-
var __privateSet$
|
|
952
|
-
__accessCheck$
|
|
953
|
+
var __privateSet$9 = (obj, member, value, setter) => {
|
|
954
|
+
__accessCheck$a(obj, member, "write to private field");
|
|
953
955
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
954
956
|
return value;
|
|
955
957
|
};
|
|
@@ -957,25 +959,25 @@ var _hasStarted$1, _startupTasks$1, _hasShutdown, _shutdownTasks;
|
|
|
957
959
|
class BackendLifecycleImpl {
|
|
958
960
|
constructor(logger) {
|
|
959
961
|
this.logger = logger;
|
|
960
|
-
__privateAdd$
|
|
961
|
-
__privateAdd$
|
|
962
|
-
__privateAdd$
|
|
963
|
-
__privateAdd$
|
|
962
|
+
__privateAdd$a(this, _hasStarted$1, false);
|
|
963
|
+
__privateAdd$a(this, _startupTasks$1, []);
|
|
964
|
+
__privateAdd$a(this, _hasShutdown, false);
|
|
965
|
+
__privateAdd$a(this, _shutdownTasks, []);
|
|
964
966
|
}
|
|
965
967
|
addStartupHook(hook, options) {
|
|
966
|
-
if (__privateGet$
|
|
968
|
+
if (__privateGet$9(this, _hasStarted$1)) {
|
|
967
969
|
throw new Error("Attempted to add startup hook after startup");
|
|
968
970
|
}
|
|
969
|
-
__privateGet$
|
|
971
|
+
__privateGet$9(this, _startupTasks$1).push({ hook, options });
|
|
970
972
|
}
|
|
971
973
|
async startup() {
|
|
972
|
-
if (__privateGet$
|
|
974
|
+
if (__privateGet$9(this, _hasStarted$1)) {
|
|
973
975
|
return;
|
|
974
976
|
}
|
|
975
|
-
__privateSet$
|
|
976
|
-
this.logger.debug(`Running ${__privateGet$
|
|
977
|
+
__privateSet$9(this, _hasStarted$1, true);
|
|
978
|
+
this.logger.debug(`Running ${__privateGet$9(this, _startupTasks$1).length} startup tasks...`);
|
|
977
979
|
await Promise.all(
|
|
978
|
-
__privateGet$
|
|
980
|
+
__privateGet$9(this, _startupTasks$1).map(async ({ hook, options }) => {
|
|
979
981
|
var _a;
|
|
980
982
|
const logger = (_a = options == null ? void 0 : options.logger) != null ? _a : this.logger;
|
|
981
983
|
try {
|
|
@@ -988,21 +990,21 @@ class BackendLifecycleImpl {
|
|
|
988
990
|
);
|
|
989
991
|
}
|
|
990
992
|
addShutdownHook(hook, options) {
|
|
991
|
-
if (__privateGet$
|
|
993
|
+
if (__privateGet$9(this, _hasShutdown)) {
|
|
992
994
|
throw new Error("Attempted to add shutdown hook after shutdown");
|
|
993
995
|
}
|
|
994
|
-
__privateGet$
|
|
996
|
+
__privateGet$9(this, _shutdownTasks).push({ hook, options });
|
|
995
997
|
}
|
|
996
998
|
async shutdown() {
|
|
997
|
-
if (__privateGet$
|
|
999
|
+
if (__privateGet$9(this, _hasShutdown)) {
|
|
998
1000
|
return;
|
|
999
1001
|
}
|
|
1000
|
-
__privateSet$
|
|
1002
|
+
__privateSet$9(this, _hasShutdown, true);
|
|
1001
1003
|
this.logger.debug(
|
|
1002
|
-
`Running ${__privateGet$
|
|
1004
|
+
`Running ${__privateGet$9(this, _shutdownTasks).length} shutdown tasks...`
|
|
1003
1005
|
);
|
|
1004
1006
|
await Promise.all(
|
|
1005
|
-
__privateGet$
|
|
1007
|
+
__privateGet$9(this, _shutdownTasks).map(async ({ hook, options }) => {
|
|
1006
1008
|
var _a;
|
|
1007
1009
|
const logger = (_a = options == null ? void 0 : options.logger) != null ? _a : this.logger;
|
|
1008
1010
|
try {
|
|
@@ -1029,21 +1031,21 @@ const rootLifecycleServiceFactory = backendPluginApi.createServiceFactory({
|
|
|
1029
1031
|
}
|
|
1030
1032
|
});
|
|
1031
1033
|
|
|
1032
|
-
var __accessCheck$
|
|
1034
|
+
var __accessCheck$9 = (obj, member, msg) => {
|
|
1033
1035
|
if (!member.has(obj))
|
|
1034
1036
|
throw TypeError("Cannot " + msg);
|
|
1035
1037
|
};
|
|
1036
|
-
var __privateGet$
|
|
1037
|
-
__accessCheck$
|
|
1038
|
+
var __privateGet$8 = (obj, member, getter) => {
|
|
1039
|
+
__accessCheck$9(obj, member, "read from private field");
|
|
1038
1040
|
return getter ? getter.call(obj) : member.get(obj);
|
|
1039
1041
|
};
|
|
1040
|
-
var __privateAdd$
|
|
1042
|
+
var __privateAdd$9 = (obj, member, value) => {
|
|
1041
1043
|
if (member.has(obj))
|
|
1042
1044
|
throw TypeError("Cannot add the same private member more than once");
|
|
1043
1045
|
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
1044
1046
|
};
|
|
1045
|
-
var __privateSet$
|
|
1046
|
-
__accessCheck$
|
|
1047
|
+
var __privateSet$8 = (obj, member, value, setter) => {
|
|
1048
|
+
__accessCheck$9(obj, member, "write to private field");
|
|
1047
1049
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
1048
1050
|
return value;
|
|
1049
1051
|
};
|
|
@@ -1053,25 +1055,25 @@ class BackendPluginLifecycleImpl {
|
|
|
1053
1055
|
this.logger = logger;
|
|
1054
1056
|
this.rootLifecycle = rootLifecycle;
|
|
1055
1057
|
this.pluginMetadata = pluginMetadata;
|
|
1056
|
-
__privateAdd$
|
|
1057
|
-
__privateAdd$
|
|
1058
|
+
__privateAdd$9(this, _hasStarted, false);
|
|
1059
|
+
__privateAdd$9(this, _startupTasks, []);
|
|
1058
1060
|
}
|
|
1059
1061
|
addStartupHook(hook, options) {
|
|
1060
|
-
if (__privateGet$
|
|
1062
|
+
if (__privateGet$8(this, _hasStarted)) {
|
|
1061
1063
|
throw new Error("Attempted to add startup hook after startup");
|
|
1062
1064
|
}
|
|
1063
|
-
__privateGet$
|
|
1065
|
+
__privateGet$8(this, _startupTasks).push({ hook, options });
|
|
1064
1066
|
}
|
|
1065
1067
|
async startup() {
|
|
1066
|
-
if (__privateGet$
|
|
1068
|
+
if (__privateGet$8(this, _hasStarted)) {
|
|
1067
1069
|
return;
|
|
1068
1070
|
}
|
|
1069
|
-
__privateSet$
|
|
1071
|
+
__privateSet$8(this, _hasStarted, true);
|
|
1070
1072
|
this.logger.debug(
|
|
1071
|
-
`Running ${__privateGet$
|
|
1073
|
+
`Running ${__privateGet$8(this, _startupTasks).length} plugin startup tasks...`
|
|
1072
1074
|
);
|
|
1073
1075
|
await Promise.all(
|
|
1074
|
-
__privateGet$
|
|
1076
|
+
__privateGet$8(this, _startupTasks).map(async ({ hook, options }) => {
|
|
1075
1077
|
var _a;
|
|
1076
1078
|
const logger = (_a = options == null ? void 0 : options.logger) != null ? _a : this.logger;
|
|
1077
1079
|
try {
|
|
@@ -1109,26 +1111,26 @@ const lifecycleServiceFactory = backendPluginApi.createServiceFactory({
|
|
|
1109
1111
|
}
|
|
1110
1112
|
});
|
|
1111
1113
|
|
|
1112
|
-
var __accessCheck$
|
|
1114
|
+
var __accessCheck$8 = (obj, member, msg) => {
|
|
1113
1115
|
if (!member.has(obj))
|
|
1114
1116
|
throw TypeError("Cannot " + msg);
|
|
1115
1117
|
};
|
|
1116
|
-
var __privateGet$
|
|
1117
|
-
__accessCheck$
|
|
1118
|
+
var __privateGet$7 = (obj, member, getter) => {
|
|
1119
|
+
__accessCheck$8(obj, member, "read from private field");
|
|
1118
1120
|
return getter ? getter.call(obj) : member.get(obj);
|
|
1119
1121
|
};
|
|
1120
|
-
var __privateAdd$
|
|
1122
|
+
var __privateAdd$8 = (obj, member, value) => {
|
|
1121
1123
|
if (member.has(obj))
|
|
1122
1124
|
throw TypeError("Cannot add the same private member more than once");
|
|
1123
1125
|
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
1124
1126
|
};
|
|
1125
|
-
var __privateSet$
|
|
1126
|
-
__accessCheck$
|
|
1127
|
+
var __privateSet$7 = (obj, member, value, setter) => {
|
|
1128
|
+
__accessCheck$8(obj, member, "write to private field");
|
|
1127
1129
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
1128
1130
|
return value;
|
|
1129
1131
|
};
|
|
1130
|
-
var __privateMethod$
|
|
1131
|
-
__accessCheck$
|
|
1132
|
+
var __privateMethod$6 = (obj, member, method) => {
|
|
1133
|
+
__accessCheck$8(obj, member, "access private method");
|
|
1132
1134
|
return method;
|
|
1133
1135
|
};
|
|
1134
1136
|
var _nodeIds, _cycleKeys, _getCycleKey, getCycleKey_fn, _nodes, _allProvided;
|
|
@@ -1148,21 +1150,21 @@ class Node {
|
|
|
1148
1150
|
}
|
|
1149
1151
|
const _CycleKeySet = class _CycleKeySet {
|
|
1150
1152
|
constructor(nodes) {
|
|
1151
|
-
__privateAdd$
|
|
1152
|
-
__privateAdd$
|
|
1153
|
-
__privateAdd$
|
|
1154
|
-
__privateSet$
|
|
1155
|
-
__privateSet$
|
|
1153
|
+
__privateAdd$8(this, _getCycleKey);
|
|
1154
|
+
__privateAdd$8(this, _nodeIds, void 0);
|
|
1155
|
+
__privateAdd$8(this, _cycleKeys, void 0);
|
|
1156
|
+
__privateSet$7(this, _nodeIds, new Map(nodes.map((n, i) => [n.value, i])));
|
|
1157
|
+
__privateSet$7(this, _cycleKeys, /* @__PURE__ */ new Set());
|
|
1156
1158
|
}
|
|
1157
1159
|
static from(nodes) {
|
|
1158
1160
|
return new _CycleKeySet(nodes);
|
|
1159
1161
|
}
|
|
1160
1162
|
tryAdd(path) {
|
|
1161
|
-
const cycleKey = __privateMethod$
|
|
1162
|
-
if (__privateGet$
|
|
1163
|
+
const cycleKey = __privateMethod$6(this, _getCycleKey, getCycleKey_fn).call(this, path);
|
|
1164
|
+
if (__privateGet$7(this, _cycleKeys).has(cycleKey)) {
|
|
1163
1165
|
return false;
|
|
1164
1166
|
}
|
|
1165
|
-
__privateGet$
|
|
1167
|
+
__privateGet$7(this, _cycleKeys).add(cycleKey);
|
|
1166
1168
|
return true;
|
|
1167
1169
|
}
|
|
1168
1170
|
};
|
|
@@ -1170,18 +1172,18 @@ _nodeIds = new WeakMap();
|
|
|
1170
1172
|
_cycleKeys = new WeakMap();
|
|
1171
1173
|
_getCycleKey = new WeakSet();
|
|
1172
1174
|
getCycleKey_fn = function(path) {
|
|
1173
|
-
return path.map((n) => __privateGet$
|
|
1175
|
+
return path.map((n) => __privateGet$7(this, _nodeIds).get(n)).sort().join(",");
|
|
1174
1176
|
};
|
|
1175
1177
|
let CycleKeySet = _CycleKeySet;
|
|
1176
1178
|
const _DependencyGraph = class _DependencyGraph {
|
|
1177
1179
|
constructor(nodes) {
|
|
1178
|
-
__privateAdd$
|
|
1179
|
-
__privateAdd$
|
|
1180
|
-
__privateSet$
|
|
1181
|
-
__privateSet$
|
|
1182
|
-
for (const node of __privateGet$
|
|
1180
|
+
__privateAdd$8(this, _nodes, void 0);
|
|
1181
|
+
__privateAdd$8(this, _allProvided, void 0);
|
|
1182
|
+
__privateSet$7(this, _nodes, nodes);
|
|
1183
|
+
__privateSet$7(this, _allProvided, /* @__PURE__ */ new Set());
|
|
1184
|
+
for (const node of __privateGet$7(this, _nodes).values()) {
|
|
1183
1185
|
for (const produced of node.provides) {
|
|
1184
|
-
__privateGet$
|
|
1186
|
+
__privateGet$7(this, _allProvided).add(produced);
|
|
1185
1187
|
}
|
|
1186
1188
|
}
|
|
1187
1189
|
}
|
|
@@ -1205,9 +1207,9 @@ const _DependencyGraph = class _DependencyGraph {
|
|
|
1205
1207
|
*/
|
|
1206
1208
|
findUnsatisfiedDeps() {
|
|
1207
1209
|
const unsatisfiedDependencies = [];
|
|
1208
|
-
for (const node of __privateGet$
|
|
1210
|
+
for (const node of __privateGet$7(this, _nodes).values()) {
|
|
1209
1211
|
const unsatisfied = Array.from(node.consumes).filter(
|
|
1210
|
-
(id) => !__privateGet$
|
|
1212
|
+
(id) => !__privateGet$7(this, _allProvided).has(id)
|
|
1211
1213
|
);
|
|
1212
1214
|
if (unsatisfied.length > 0) {
|
|
1213
1215
|
unsatisfiedDependencies.push({ value: node.value, unsatisfied });
|
|
@@ -1227,8 +1229,8 @@ const _DependencyGraph = class _DependencyGraph {
|
|
|
1227
1229
|
* form a cycle, with the same node as the first and last element of the array.
|
|
1228
1230
|
*/
|
|
1229
1231
|
*detectCircularDependencies() {
|
|
1230
|
-
const cycleKeys = CycleKeySet.from(__privateGet$
|
|
1231
|
-
for (const startNode of __privateGet$
|
|
1232
|
+
const cycleKeys = CycleKeySet.from(__privateGet$7(this, _nodes));
|
|
1233
|
+
for (const startNode of __privateGet$7(this, _nodes)) {
|
|
1232
1234
|
const visited = /* @__PURE__ */ new Set();
|
|
1233
1235
|
const stack = new Array([
|
|
1234
1236
|
startNode,
|
|
@@ -1241,7 +1243,7 @@ const _DependencyGraph = class _DependencyGraph {
|
|
|
1241
1243
|
}
|
|
1242
1244
|
visited.add(node);
|
|
1243
1245
|
for (const consumed of node.consumes) {
|
|
1244
|
-
const providerNodes = __privateGet$
|
|
1246
|
+
const providerNodes = __privateGet$7(this, _nodes).filter(
|
|
1245
1247
|
(other) => other.provides.has(consumed)
|
|
1246
1248
|
);
|
|
1247
1249
|
for (const provider of providerNodes) {
|
|
@@ -1270,9 +1272,9 @@ const _DependencyGraph = class _DependencyGraph {
|
|
|
1270
1272
|
* Dependencies of nodes that are not produced by any other nodes will be ignored.
|
|
1271
1273
|
*/
|
|
1272
1274
|
async parallelTopologicalTraversal(fn) {
|
|
1273
|
-
const allProvided = __privateGet$
|
|
1275
|
+
const allProvided = __privateGet$7(this, _allProvided);
|
|
1274
1276
|
const producedSoFar = /* @__PURE__ */ new Set();
|
|
1275
|
-
const waiting = new Set(__privateGet$
|
|
1277
|
+
const waiting = new Set(__privateGet$7(this, _nodes).values());
|
|
1276
1278
|
const visited = /* @__PURE__ */ new Set();
|
|
1277
1279
|
const results = new Array();
|
|
1278
1280
|
let inFlight = 0;
|
|
@@ -1318,26 +1320,26 @@ _nodes = new WeakMap();
|
|
|
1318
1320
|
_allProvided = new WeakMap();
|
|
1319
1321
|
let DependencyGraph = _DependencyGraph;
|
|
1320
1322
|
|
|
1321
|
-
var __accessCheck$
|
|
1323
|
+
var __accessCheck$7 = (obj, member, msg) => {
|
|
1322
1324
|
if (!member.has(obj))
|
|
1323
1325
|
throw TypeError("Cannot " + msg);
|
|
1324
1326
|
};
|
|
1325
|
-
var __privateGet$
|
|
1326
|
-
__accessCheck$
|
|
1327
|
+
var __privateGet$6 = (obj, member, getter) => {
|
|
1328
|
+
__accessCheck$7(obj, member, "read from private field");
|
|
1327
1329
|
return getter ? getter.call(obj) : member.get(obj);
|
|
1328
1330
|
};
|
|
1329
|
-
var __privateAdd$
|
|
1331
|
+
var __privateAdd$7 = (obj, member, value) => {
|
|
1330
1332
|
if (member.has(obj))
|
|
1331
1333
|
throw TypeError("Cannot add the same private member more than once");
|
|
1332
1334
|
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
1333
1335
|
};
|
|
1334
|
-
var __privateSet$
|
|
1335
|
-
__accessCheck$
|
|
1336
|
+
var __privateSet$6 = (obj, member, value, setter) => {
|
|
1337
|
+
__accessCheck$7(obj, member, "write to private field");
|
|
1336
1338
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
1337
1339
|
return value;
|
|
1338
1340
|
};
|
|
1339
|
-
var __privateMethod$
|
|
1340
|
-
__accessCheck$
|
|
1341
|
+
var __privateMethod$5 = (obj, member, method) => {
|
|
1342
|
+
__accessCheck$7(obj, member, "access private method");
|
|
1341
1343
|
return method;
|
|
1342
1344
|
};
|
|
1343
1345
|
var _providedFactories, _loadedDefaultFactories, _implementations, _rootServiceImplementations, _addedFactoryIds, _instantiatedFactories, _resolveFactory, resolveFactory_fn, _checkForMissingDeps, checkForMissingDeps_fn;
|
|
@@ -1360,19 +1362,19 @@ const pluginMetadataServiceFactory = backendPluginApi.createServiceFactory(
|
|
|
1360
1362
|
);
|
|
1361
1363
|
const _ServiceRegistry = class _ServiceRegistry {
|
|
1362
1364
|
constructor(factories) {
|
|
1363
|
-
__privateAdd$
|
|
1364
|
-
__privateAdd$
|
|
1365
|
-
__privateAdd$
|
|
1366
|
-
__privateAdd$
|
|
1367
|
-
__privateAdd$
|
|
1368
|
-
__privateAdd$
|
|
1369
|
-
__privateAdd$
|
|
1370
|
-
__privateAdd$
|
|
1371
|
-
__privateSet$
|
|
1365
|
+
__privateAdd$7(this, _resolveFactory);
|
|
1366
|
+
__privateAdd$7(this, _checkForMissingDeps);
|
|
1367
|
+
__privateAdd$7(this, _providedFactories, void 0);
|
|
1368
|
+
__privateAdd$7(this, _loadedDefaultFactories, void 0);
|
|
1369
|
+
__privateAdd$7(this, _implementations, void 0);
|
|
1370
|
+
__privateAdd$7(this, _rootServiceImplementations, /* @__PURE__ */ new Map());
|
|
1371
|
+
__privateAdd$7(this, _addedFactoryIds, /* @__PURE__ */ new Set());
|
|
1372
|
+
__privateAdd$7(this, _instantiatedFactories, /* @__PURE__ */ new Set());
|
|
1373
|
+
__privateSet$6(this, _providedFactories, new Map(
|
|
1372
1374
|
factories.map((sf) => [sf.service.id, toInternalServiceFactory(sf)])
|
|
1373
1375
|
));
|
|
1374
|
-
__privateSet$
|
|
1375
|
-
__privateSet$
|
|
1376
|
+
__privateSet$6(this, _loadedDefaultFactories, /* @__PURE__ */ new Map());
|
|
1377
|
+
__privateSet$6(this, _implementations, /* @__PURE__ */ new Map());
|
|
1376
1378
|
}
|
|
1377
1379
|
static create(factories) {
|
|
1378
1380
|
const registry = new _ServiceRegistry(factories);
|
|
@@ -1381,7 +1383,7 @@ const _ServiceRegistry = class _ServiceRegistry {
|
|
|
1381
1383
|
}
|
|
1382
1384
|
checkForCircularDeps() {
|
|
1383
1385
|
const graph = DependencyGraph.fromIterable(
|
|
1384
|
-
Array.from(__privateGet$
|
|
1386
|
+
Array.from(__privateGet$6(this, _providedFactories)).map(
|
|
1385
1387
|
([serviceId, serviceFactory]) => ({
|
|
1386
1388
|
value: serviceId,
|
|
1387
1389
|
provides: [serviceId],
|
|
@@ -1403,30 +1405,38 @@ const _ServiceRegistry = class _ServiceRegistry {
|
|
|
1403
1405
|
`The ${backendPluginApi.coreServices.pluginMetadata.id} service cannot be overridden`
|
|
1404
1406
|
);
|
|
1405
1407
|
}
|
|
1406
|
-
if (__privateGet$
|
|
1408
|
+
if (__privateGet$6(this, _addedFactoryIds).has(factoryId)) {
|
|
1407
1409
|
throw new Error(
|
|
1408
1410
|
`Duplicate service implementations provided for ${factoryId}`
|
|
1409
1411
|
);
|
|
1410
1412
|
}
|
|
1411
|
-
if (__privateGet$
|
|
1413
|
+
if (__privateGet$6(this, _instantiatedFactories).has(factoryId)) {
|
|
1412
1414
|
throw new Error(
|
|
1413
1415
|
`Unable to set service factory with id ${factoryId}, service has already been instantiated`
|
|
1414
1416
|
);
|
|
1415
1417
|
}
|
|
1416
|
-
__privateGet$
|
|
1417
|
-
__privateGet$
|
|
1418
|
+
__privateGet$6(this, _addedFactoryIds).add(factoryId);
|
|
1419
|
+
__privateGet$6(this, _providedFactories).set(factoryId, toInternalServiceFactory(factory));
|
|
1418
1420
|
}
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
+
async initializeEagerServicesWithScope(scope, pluginId = "root") {
|
|
1422
|
+
for (const factory of __privateGet$6(this, _providedFactories).values()) {
|
|
1423
|
+
if (factory.service.scope === scope) {
|
|
1424
|
+
if (scope === "root" && factory.initialization !== "lazy") {
|
|
1425
|
+
await this.get(factory.service, pluginId);
|
|
1426
|
+
} else if (scope === "plugin" && factory.initialization === "always") {
|
|
1427
|
+
await this.get(factory.service, pluginId);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1421
1431
|
}
|
|
1422
1432
|
get(ref, pluginId) {
|
|
1423
1433
|
var _a;
|
|
1424
|
-
__privateGet$
|
|
1425
|
-
return (_a = __privateMethod$
|
|
1434
|
+
__privateGet$6(this, _instantiatedFactories).add(ref.id);
|
|
1435
|
+
return (_a = __privateMethod$5(this, _resolveFactory, resolveFactory_fn).call(this, ref, pluginId)) == null ? void 0 : _a.then((factory) => {
|
|
1426
1436
|
if (factory.service.scope === "root") {
|
|
1427
|
-
let existing = __privateGet$
|
|
1437
|
+
let existing = __privateGet$6(this, _rootServiceImplementations).get(factory);
|
|
1428
1438
|
if (!existing) {
|
|
1429
|
-
__privateMethod$
|
|
1439
|
+
__privateMethod$5(this, _checkForMissingDeps, checkForMissingDeps_fn).call(this, factory, pluginId);
|
|
1430
1440
|
const rootDeps = new Array();
|
|
1431
1441
|
for (const [name, serviceRef] of Object.entries(factory.deps)) {
|
|
1432
1442
|
if (serviceRef.scope !== "root") {
|
|
@@ -1440,13 +1450,13 @@ const _ServiceRegistry = class _ServiceRegistry {
|
|
|
1440
1450
|
existing = Promise.all(rootDeps).then(
|
|
1441
1451
|
(entries) => factory.factory(Object.fromEntries(entries), void 0)
|
|
1442
1452
|
);
|
|
1443
|
-
__privateGet$
|
|
1453
|
+
__privateGet$6(this, _rootServiceImplementations).set(factory, existing);
|
|
1444
1454
|
}
|
|
1445
1455
|
return existing;
|
|
1446
1456
|
}
|
|
1447
|
-
let implementation = __privateGet$
|
|
1457
|
+
let implementation = __privateGet$6(this, _implementations).get(factory);
|
|
1448
1458
|
if (!implementation) {
|
|
1449
|
-
__privateMethod$
|
|
1459
|
+
__privateMethod$5(this, _checkForMissingDeps, checkForMissingDeps_fn).call(this, factory, pluginId);
|
|
1450
1460
|
const rootDeps = new Array();
|
|
1451
1461
|
for (const [name, serviceRef] of Object.entries(factory.deps)) {
|
|
1452
1462
|
if (serviceRef.scope === "root") {
|
|
@@ -1468,7 +1478,7 @@ const _ServiceRegistry = class _ServiceRegistry {
|
|
|
1468
1478
|
}),
|
|
1469
1479
|
byPlugin: /* @__PURE__ */ new Map()
|
|
1470
1480
|
};
|
|
1471
|
-
__privateGet$
|
|
1481
|
+
__privateGet$6(this, _implementations).set(factory, implementation);
|
|
1472
1482
|
}
|
|
1473
1483
|
let result = implementation.byPlugin.get(pluginId);
|
|
1474
1484
|
if (!result) {
|
|
@@ -1506,18 +1516,18 @@ resolveFactory_fn = function(ref, pluginId) {
|
|
|
1506
1516
|
toInternalServiceFactory(pluginMetadataServiceFactory({ pluginId }))
|
|
1507
1517
|
);
|
|
1508
1518
|
}
|
|
1509
|
-
let resolvedFactory = __privateGet$
|
|
1519
|
+
let resolvedFactory = __privateGet$6(this, _providedFactories).get(ref.id);
|
|
1510
1520
|
const { __defaultFactory: defaultFactory } = ref;
|
|
1511
1521
|
if (!resolvedFactory && !defaultFactory) {
|
|
1512
1522
|
return void 0;
|
|
1513
1523
|
}
|
|
1514
1524
|
if (!resolvedFactory) {
|
|
1515
|
-
let loadedFactory = __privateGet$
|
|
1525
|
+
let loadedFactory = __privateGet$6(this, _loadedDefaultFactories).get(defaultFactory);
|
|
1516
1526
|
if (!loadedFactory) {
|
|
1517
1527
|
loadedFactory = Promise.resolve().then(() => defaultFactory(ref)).then(
|
|
1518
1528
|
(f) => toInternalServiceFactory(typeof f === "function" ? f() : f)
|
|
1519
1529
|
);
|
|
1520
|
-
__privateGet$
|
|
1530
|
+
__privateGet$6(this, _loadedDefaultFactories).set(defaultFactory, loadedFactory);
|
|
1521
1531
|
}
|
|
1522
1532
|
resolvedFactory = loadedFactory.catch((error) => {
|
|
1523
1533
|
throw new Error(
|
|
@@ -1535,7 +1545,7 @@ checkForMissingDeps_fn = function(factory, pluginId) {
|
|
|
1535
1545
|
if (ref.id === backendPluginApi.coreServices.pluginMetadata.id) {
|
|
1536
1546
|
return false;
|
|
1537
1547
|
}
|
|
1538
|
-
if (__privateGet$
|
|
1548
|
+
if (__privateGet$6(this, _providedFactories).get(ref.id)) {
|
|
1539
1549
|
return false;
|
|
1540
1550
|
}
|
|
1541
1551
|
return !ref.__defaultFactory;
|
|
@@ -1549,52 +1559,52 @@ checkForMissingDeps_fn = function(factory, pluginId) {
|
|
|
1549
1559
|
};
|
|
1550
1560
|
let ServiceRegistry = _ServiceRegistry;
|
|
1551
1561
|
|
|
1552
|
-
var __accessCheck$
|
|
1562
|
+
var __accessCheck$6 = (obj, member, msg) => {
|
|
1553
1563
|
if (!member.has(obj))
|
|
1554
1564
|
throw TypeError("Cannot " + msg);
|
|
1555
1565
|
};
|
|
1556
|
-
var __privateGet$
|
|
1557
|
-
__accessCheck$
|
|
1566
|
+
var __privateGet$5 = (obj, member, getter) => {
|
|
1567
|
+
__accessCheck$6(obj, member, "read from private field");
|
|
1558
1568
|
return getter ? getter.call(obj) : member.get(obj);
|
|
1559
1569
|
};
|
|
1560
|
-
var __privateAdd$
|
|
1570
|
+
var __privateAdd$6 = (obj, member, value) => {
|
|
1561
1571
|
if (member.has(obj))
|
|
1562
1572
|
throw TypeError("Cannot add the same private member more than once");
|
|
1563
1573
|
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
1564
1574
|
};
|
|
1565
|
-
var __privateSet$
|
|
1566
|
-
__accessCheck$
|
|
1575
|
+
var __privateSet$5 = (obj, member, value, setter) => {
|
|
1576
|
+
__accessCheck$6(obj, member, "write to private field");
|
|
1567
1577
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
1568
1578
|
return value;
|
|
1569
1579
|
};
|
|
1570
|
-
var __privateMethod$
|
|
1571
|
-
__accessCheck$
|
|
1580
|
+
var __privateMethod$4 = (obj, member, method) => {
|
|
1581
|
+
__accessCheck$6(obj, member, "access private method");
|
|
1572
1582
|
return method;
|
|
1573
1583
|
};
|
|
1574
1584
|
var _startPromise, _features, _extensionPoints, _serviceRegistry, _registeredFeatures, _getInitDeps, getInitDeps_fn, _addFeature, addFeature_fn, _doStart, doStart_fn, _getRootLifecycleImpl, getRootLifecycleImpl_fn, _getPluginLifecycleImpl, getPluginLifecycleImpl_fn;
|
|
1575
1585
|
class BackendInitializer {
|
|
1576
1586
|
constructor(defaultApiFactories) {
|
|
1577
|
-
__privateAdd$
|
|
1578
|
-
__privateAdd$
|
|
1579
|
-
__privateAdd$
|
|
1587
|
+
__privateAdd$6(this, _getInitDeps);
|
|
1588
|
+
__privateAdd$6(this, _addFeature);
|
|
1589
|
+
__privateAdd$6(this, _doStart);
|
|
1580
1590
|
// Bit of a hacky way to grab the lifecycle services, potentially find a nicer way to do this
|
|
1581
|
-
__privateAdd$
|
|
1582
|
-
__privateAdd$
|
|
1583
|
-
__privateAdd$
|
|
1584
|
-
__privateAdd$
|
|
1585
|
-
__privateAdd$
|
|
1586
|
-
__privateAdd$
|
|
1587
|
-
__privateAdd$
|
|
1588
|
-
__privateSet$
|
|
1591
|
+
__privateAdd$6(this, _getRootLifecycleImpl);
|
|
1592
|
+
__privateAdd$6(this, _getPluginLifecycleImpl);
|
|
1593
|
+
__privateAdd$6(this, _startPromise, void 0);
|
|
1594
|
+
__privateAdd$6(this, _features, new Array());
|
|
1595
|
+
__privateAdd$6(this, _extensionPoints, /* @__PURE__ */ new Map());
|
|
1596
|
+
__privateAdd$6(this, _serviceRegistry, void 0);
|
|
1597
|
+
__privateAdd$6(this, _registeredFeatures, new Array());
|
|
1598
|
+
__privateSet$5(this, _serviceRegistry, ServiceRegistry.create([...defaultApiFactories]));
|
|
1589
1599
|
}
|
|
1590
1600
|
add(feature) {
|
|
1591
|
-
if (__privateGet$
|
|
1601
|
+
if (__privateGet$5(this, _startPromise)) {
|
|
1592
1602
|
throw new Error("feature can not be added after the backend has started");
|
|
1593
1603
|
}
|
|
1594
|
-
__privateGet$
|
|
1604
|
+
__privateGet$5(this, _registeredFeatures).push(Promise.resolve(feature));
|
|
1595
1605
|
}
|
|
1596
1606
|
async start() {
|
|
1597
|
-
if (__privateGet$
|
|
1607
|
+
if (__privateGet$5(this, _startPromise)) {
|
|
1598
1608
|
throw new Error("Backend has already started");
|
|
1599
1609
|
}
|
|
1600
1610
|
const exitHandler = async () => {
|
|
@@ -1612,18 +1622,18 @@ class BackendInitializer {
|
|
|
1612
1622
|
process.addListener("SIGTERM", exitHandler);
|
|
1613
1623
|
process.addListener("SIGINT", exitHandler);
|
|
1614
1624
|
process.addListener("beforeExit", exitHandler);
|
|
1615
|
-
__privateSet$
|
|
1616
|
-
await __privateGet$
|
|
1625
|
+
__privateSet$5(this, _startPromise, __privateMethod$4(this, _doStart, doStart_fn).call(this));
|
|
1626
|
+
await __privateGet$5(this, _startPromise);
|
|
1617
1627
|
}
|
|
1618
1628
|
async stop() {
|
|
1619
|
-
if (!__privateGet$
|
|
1629
|
+
if (!__privateGet$5(this, _startPromise)) {
|
|
1620
1630
|
return;
|
|
1621
1631
|
}
|
|
1622
1632
|
try {
|
|
1623
|
-
await __privateGet$
|
|
1633
|
+
await __privateGet$5(this, _startPromise);
|
|
1624
1634
|
} catch (error) {
|
|
1625
1635
|
}
|
|
1626
|
-
const lifecycleService = await __privateMethod$
|
|
1636
|
+
const lifecycleService = await __privateMethod$4(this, _getRootLifecycleImpl, getRootLifecycleImpl_fn).call(this);
|
|
1627
1637
|
await lifecycleService.shutdown();
|
|
1628
1638
|
}
|
|
1629
1639
|
}
|
|
@@ -1637,7 +1647,7 @@ getInitDeps_fn = async function(deps, pluginId, moduleId) {
|
|
|
1637
1647
|
const result = /* @__PURE__ */ new Map();
|
|
1638
1648
|
const missingRefs = /* @__PURE__ */ new Set();
|
|
1639
1649
|
for (const [name, ref] of Object.entries(deps)) {
|
|
1640
|
-
const ep = __privateGet$
|
|
1650
|
+
const ep = __privateGet$5(this, _extensionPoints).get(ref.id);
|
|
1641
1651
|
if (ep) {
|
|
1642
1652
|
if (ep.pluginId !== pluginId) {
|
|
1643
1653
|
throw new Error(
|
|
@@ -1646,7 +1656,7 @@ getInitDeps_fn = async function(deps, pluginId, moduleId) {
|
|
|
1646
1656
|
}
|
|
1647
1657
|
result.set(name, ep.impl);
|
|
1648
1658
|
} else {
|
|
1649
|
-
const impl = await __privateGet$
|
|
1659
|
+
const impl = await __privateGet$5(this, _serviceRegistry).get(
|
|
1650
1660
|
ref,
|
|
1651
1661
|
pluginId
|
|
1652
1662
|
);
|
|
@@ -1673,14 +1683,14 @@ addFeature_fn = function(feature) {
|
|
|
1673
1683
|
);
|
|
1674
1684
|
}
|
|
1675
1685
|
if (isServiceFactory(feature)) {
|
|
1676
|
-
__privateGet$
|
|
1686
|
+
__privateGet$5(this, _serviceRegistry).add(feature);
|
|
1677
1687
|
} else if (isInternalBackendFeature(feature)) {
|
|
1678
1688
|
if (feature.version !== "v1") {
|
|
1679
1689
|
throw new Error(
|
|
1680
1690
|
`Failed to add feature, invalid version '${feature.version}'`
|
|
1681
1691
|
);
|
|
1682
1692
|
}
|
|
1683
|
-
__privateGet$
|
|
1693
|
+
__privateGet$5(this, _features).push(feature);
|
|
1684
1694
|
} else {
|
|
1685
1695
|
throw new Error(
|
|
1686
1696
|
`Failed to add feature, invalid feature ${JSON.stringify(feature)}`
|
|
@@ -1689,39 +1699,35 @@ addFeature_fn = function(feature) {
|
|
|
1689
1699
|
};
|
|
1690
1700
|
_doStart = new WeakSet();
|
|
1691
1701
|
doStart_fn = async function() {
|
|
1692
|
-
__privateGet$
|
|
1693
|
-
for (const feature of __privateGet$
|
|
1694
|
-
__privateMethod$
|
|
1702
|
+
__privateGet$5(this, _serviceRegistry).checkForCircularDeps();
|
|
1703
|
+
for (const feature of __privateGet$5(this, _registeredFeatures)) {
|
|
1704
|
+
__privateMethod$4(this, _addFeature, addFeature_fn).call(this, await feature);
|
|
1695
1705
|
}
|
|
1696
|
-
const featureDiscovery = await __privateGet$
|
|
1706
|
+
const featureDiscovery = await __privateGet$5(this, _serviceRegistry).get(
|
|
1697
1707
|
alpha.featureDiscoveryServiceRef,
|
|
1698
1708
|
"root"
|
|
1699
1709
|
);
|
|
1700
1710
|
if (featureDiscovery) {
|
|
1701
1711
|
const { features } = await featureDiscovery.getBackendFeatures();
|
|
1702
1712
|
for (const feature of features) {
|
|
1703
|
-
__privateMethod$
|
|
1704
|
-
}
|
|
1705
|
-
__privateGet$3(this, _serviceRegistry).checkForCircularDeps();
|
|
1706
|
-
}
|
|
1707
|
-
for (const ref of __privateGet$3(this, _serviceRegistry).getServiceRefs()) {
|
|
1708
|
-
if (ref.scope === "root") {
|
|
1709
|
-
await __privateGet$3(this, _serviceRegistry).get(ref, "root");
|
|
1713
|
+
__privateMethod$4(this, _addFeature, addFeature_fn).call(this, feature);
|
|
1710
1714
|
}
|
|
1715
|
+
__privateGet$5(this, _serviceRegistry).checkForCircularDeps();
|
|
1711
1716
|
}
|
|
1717
|
+
await __privateGet$5(this, _serviceRegistry).initializeEagerServicesWithScope("root");
|
|
1712
1718
|
const pluginInits = /* @__PURE__ */ new Map();
|
|
1713
1719
|
const moduleInits = /* @__PURE__ */ new Map();
|
|
1714
|
-
for (const feature of __privateGet$
|
|
1720
|
+
for (const feature of __privateGet$5(this, _features)) {
|
|
1715
1721
|
for (const r of feature.getRegistrations()) {
|
|
1716
1722
|
const provides = /* @__PURE__ */ new Set();
|
|
1717
1723
|
if (r.type === "plugin" || r.type === "module") {
|
|
1718
1724
|
for (const [extRef, extImpl] of r.extensionPoints) {
|
|
1719
|
-
if (__privateGet$
|
|
1725
|
+
if (__privateGet$5(this, _extensionPoints).has(extRef.id)) {
|
|
1720
1726
|
throw new Error(
|
|
1721
1727
|
`ExtensionPoint with ID '${extRef.id}' is already registered`
|
|
1722
1728
|
);
|
|
1723
1729
|
}
|
|
1724
|
-
__privateGet$
|
|
1730
|
+
__privateGet$5(this, _extensionPoints).set(extRef.id, {
|
|
1725
1731
|
impl: extImpl,
|
|
1726
1732
|
pluginId: r.pluginId
|
|
1727
1733
|
});
|
|
@@ -1756,11 +1762,13 @@ doStart_fn = async function() {
|
|
|
1756
1762
|
}
|
|
1757
1763
|
}
|
|
1758
1764
|
}
|
|
1759
|
-
const allPluginIds = [
|
|
1760
|
-
.../* @__PURE__ */ new Set([...pluginInits.keys(), ...moduleInits.keys()])
|
|
1761
|
-
];
|
|
1765
|
+
const allPluginIds = [...pluginInits.keys()];
|
|
1762
1766
|
await Promise.all(
|
|
1763
1767
|
allPluginIds.map(async (pluginId) => {
|
|
1768
|
+
await __privateGet$5(this, _serviceRegistry).initializeEagerServicesWithScope(
|
|
1769
|
+
"plugin",
|
|
1770
|
+
pluginId
|
|
1771
|
+
);
|
|
1764
1772
|
const modules = moduleInits.get(pluginId);
|
|
1765
1773
|
if (modules) {
|
|
1766
1774
|
const tree = DependencyGraph.fromIterable(
|
|
@@ -1781,7 +1789,7 @@ doStart_fn = async function() {
|
|
|
1781
1789
|
}
|
|
1782
1790
|
await tree.parallelTopologicalTraversal(
|
|
1783
1791
|
async ({ moduleId, moduleInit }) => {
|
|
1784
|
-
const moduleDeps = await __privateMethod$
|
|
1792
|
+
const moduleDeps = await __privateMethod$4(this, _getInitDeps, getInitDeps_fn).call(this, moduleInit.init.deps, pluginId, moduleId);
|
|
1785
1793
|
await moduleInit.init.func(moduleDeps).catch((error) => {
|
|
1786
1794
|
throw new errors.ForwardedError(
|
|
1787
1795
|
`Module '${moduleId}' for plugin '${pluginId}' startup failed`,
|
|
@@ -1793,7 +1801,7 @@ doStart_fn = async function() {
|
|
|
1793
1801
|
}
|
|
1794
1802
|
const pluginInit = pluginInits.get(pluginId);
|
|
1795
1803
|
if (pluginInit) {
|
|
1796
|
-
const pluginDeps = await __privateMethod$
|
|
1804
|
+
const pluginDeps = await __privateMethod$4(this, _getInitDeps, getInitDeps_fn).call(this, pluginInit.init.deps, pluginId);
|
|
1797
1805
|
await pluginInit.init.func(pluginDeps).catch((error) => {
|
|
1798
1806
|
throw new errors.ForwardedError(
|
|
1799
1807
|
`Plugin '${pluginId}' startup failed`,
|
|
@@ -1801,14 +1809,14 @@ doStart_fn = async function() {
|
|
|
1801
1809
|
);
|
|
1802
1810
|
});
|
|
1803
1811
|
}
|
|
1804
|
-
const lifecycleService2 = await __privateMethod$
|
|
1812
|
+
const lifecycleService2 = await __privateMethod$4(this, _getPluginLifecycleImpl, getPluginLifecycleImpl_fn).call(this, pluginId);
|
|
1805
1813
|
await lifecycleService2.startup();
|
|
1806
1814
|
})
|
|
1807
1815
|
);
|
|
1808
|
-
const lifecycleService = await __privateMethod$
|
|
1816
|
+
const lifecycleService = await __privateMethod$4(this, _getRootLifecycleImpl, getRootLifecycleImpl_fn).call(this);
|
|
1809
1817
|
await lifecycleService.startup();
|
|
1810
1818
|
if (process.env.NODE_ENV !== "test") {
|
|
1811
|
-
const rootLogger = await __privateGet$
|
|
1819
|
+
const rootLogger = await __privateGet$5(this, _serviceRegistry).get(
|
|
1812
1820
|
backendPluginApi.coreServices.rootLogger,
|
|
1813
1821
|
"root"
|
|
1814
1822
|
);
|
|
@@ -1824,7 +1832,7 @@ doStart_fn = async function() {
|
|
|
1824
1832
|
};
|
|
1825
1833
|
_getRootLifecycleImpl = new WeakSet();
|
|
1826
1834
|
getRootLifecycleImpl_fn = async function() {
|
|
1827
|
-
const lifecycleService = await __privateGet$
|
|
1835
|
+
const lifecycleService = await __privateGet$5(this, _serviceRegistry).get(
|
|
1828
1836
|
backendPluginApi.coreServices.rootLifecycle,
|
|
1829
1837
|
"root"
|
|
1830
1838
|
);
|
|
@@ -1835,7 +1843,7 @@ getRootLifecycleImpl_fn = async function() {
|
|
|
1835
1843
|
};
|
|
1836
1844
|
_getPluginLifecycleImpl = new WeakSet();
|
|
1837
1845
|
getPluginLifecycleImpl_fn = async function(pluginId) {
|
|
1838
|
-
const lifecycleService = await __privateGet$
|
|
1846
|
+
const lifecycleService = await __privateGet$5(this, _serviceRegistry).get(
|
|
1839
1847
|
backendPluginApi.coreServices.lifecycle,
|
|
1840
1848
|
pluginId
|
|
1841
1849
|
);
|
|
@@ -1851,42 +1859,42 @@ function isInternalBackendFeature(feature) {
|
|
|
1851
1859
|
return typeof feature.getRegistrations === "function";
|
|
1852
1860
|
}
|
|
1853
1861
|
|
|
1854
|
-
var __accessCheck$
|
|
1862
|
+
var __accessCheck$5 = (obj, member, msg) => {
|
|
1855
1863
|
if (!member.has(obj))
|
|
1856
1864
|
throw TypeError("Cannot " + msg);
|
|
1857
1865
|
};
|
|
1858
|
-
var __privateGet$
|
|
1859
|
-
__accessCheck$
|
|
1866
|
+
var __privateGet$4 = (obj, member, getter) => {
|
|
1867
|
+
__accessCheck$5(obj, member, "read from private field");
|
|
1860
1868
|
return getter ? getter.call(obj) : member.get(obj);
|
|
1861
1869
|
};
|
|
1862
|
-
var __privateAdd$
|
|
1870
|
+
var __privateAdd$5 = (obj, member, value) => {
|
|
1863
1871
|
if (member.has(obj))
|
|
1864
1872
|
throw TypeError("Cannot add the same private member more than once");
|
|
1865
1873
|
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
1866
1874
|
};
|
|
1867
|
-
var __privateSet$
|
|
1868
|
-
__accessCheck$
|
|
1875
|
+
var __privateSet$4 = (obj, member, value, setter) => {
|
|
1876
|
+
__accessCheck$5(obj, member, "write to private field");
|
|
1869
1877
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
1870
1878
|
return value;
|
|
1871
1879
|
};
|
|
1872
1880
|
var _initializer;
|
|
1873
1881
|
class BackstageBackend {
|
|
1874
1882
|
constructor(defaultServiceFactories) {
|
|
1875
|
-
__privateAdd$
|
|
1876
|
-
__privateSet$
|
|
1883
|
+
__privateAdd$5(this, _initializer, void 0);
|
|
1884
|
+
__privateSet$4(this, _initializer, new BackendInitializer(defaultServiceFactories));
|
|
1877
1885
|
}
|
|
1878
1886
|
add(feature) {
|
|
1879
1887
|
if (isPromise(feature)) {
|
|
1880
|
-
__privateGet$
|
|
1888
|
+
__privateGet$4(this, _initializer).add(feature.then((f) => unwrapFeature(f.default)));
|
|
1881
1889
|
} else {
|
|
1882
|
-
__privateGet$
|
|
1890
|
+
__privateGet$4(this, _initializer).add(unwrapFeature(feature));
|
|
1883
1891
|
}
|
|
1884
1892
|
}
|
|
1885
1893
|
async start() {
|
|
1886
|
-
await __privateGet$
|
|
1894
|
+
await __privateGet$4(this, _initializer).start();
|
|
1887
1895
|
}
|
|
1888
1896
|
async stop() {
|
|
1889
|
-
await __privateGet$
|
|
1897
|
+
await __privateGet$4(this, _initializer).stop();
|
|
1890
1898
|
}
|
|
1891
1899
|
}
|
|
1892
1900
|
_initializer = new WeakMap();
|
|
@@ -1932,6 +1940,450 @@ function createSpecializedBackend(options) {
|
|
|
1932
1940
|
return new BackstageBackend(services);
|
|
1933
1941
|
}
|
|
1934
1942
|
|
|
1943
|
+
var __accessCheck$4 = (obj, member, msg) => {
|
|
1944
|
+
if (!member.has(obj))
|
|
1945
|
+
throw TypeError("Cannot " + msg);
|
|
1946
|
+
};
|
|
1947
|
+
var __privateGet$3 = (obj, member, getter) => {
|
|
1948
|
+
__accessCheck$4(obj, member, "read from private field");
|
|
1949
|
+
return getter ? getter.call(obj) : member.get(obj);
|
|
1950
|
+
};
|
|
1951
|
+
var __privateAdd$4 = (obj, member, value) => {
|
|
1952
|
+
if (member.has(obj))
|
|
1953
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
1954
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
1955
|
+
};
|
|
1956
|
+
var __privateSet$3 = (obj, member, value, setter) => {
|
|
1957
|
+
__accessCheck$4(obj, member, "write to private field");
|
|
1958
|
+
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
1959
|
+
return value;
|
|
1960
|
+
};
|
|
1961
|
+
var _keyStore, _keyStoreUpdated;
|
|
1962
|
+
const CLOCK_MARGIN_S = 10;
|
|
1963
|
+
class JwksClient {
|
|
1964
|
+
constructor(getEndpoint) {
|
|
1965
|
+
this.getEndpoint = getEndpoint;
|
|
1966
|
+
__privateAdd$4(this, _keyStore, void 0);
|
|
1967
|
+
__privateAdd$4(this, _keyStoreUpdated, 0);
|
|
1968
|
+
}
|
|
1969
|
+
get getKey() {
|
|
1970
|
+
if (!__privateGet$3(this, _keyStore)) {
|
|
1971
|
+
throw new errors.AuthenticationError(
|
|
1972
|
+
"refreshKeyStore must be called before jwksClient.getKey"
|
|
1973
|
+
);
|
|
1974
|
+
}
|
|
1975
|
+
return __privateGet$3(this, _keyStore);
|
|
1976
|
+
}
|
|
1977
|
+
/**
|
|
1978
|
+
* If the last keystore refresh is stale, update the keystore URL to the latest
|
|
1979
|
+
*/
|
|
1980
|
+
async refreshKeyStore(rawJwtToken) {
|
|
1981
|
+
const payload = await jose.decodeJwt(rawJwtToken);
|
|
1982
|
+
const header = await jose.decodeProtectedHeader(rawJwtToken);
|
|
1983
|
+
let keyStoreHasKey;
|
|
1984
|
+
try {
|
|
1985
|
+
if (__privateGet$3(this, _keyStore)) {
|
|
1986
|
+
const [_, rawPayload, rawSignature] = rawJwtToken.split(".");
|
|
1987
|
+
keyStoreHasKey = await __privateGet$3(this, _keyStore).call(this, header, {
|
|
1988
|
+
payload: rawPayload,
|
|
1989
|
+
signature: rawSignature
|
|
1990
|
+
});
|
|
1991
|
+
}
|
|
1992
|
+
} catch (error) {
|
|
1993
|
+
keyStoreHasKey = false;
|
|
1994
|
+
}
|
|
1995
|
+
const issuedAfterLastRefresh = (payload == null ? void 0 : payload.iat) && payload.iat > __privateGet$3(this, _keyStoreUpdated) - CLOCK_MARGIN_S;
|
|
1996
|
+
if (!__privateGet$3(this, _keyStore) || !keyStoreHasKey && issuedAfterLastRefresh) {
|
|
1997
|
+
const endpoint = await this.getEndpoint();
|
|
1998
|
+
__privateSet$3(this, _keyStore, jose.createRemoteJWKSet(endpoint));
|
|
1999
|
+
__privateSet$3(this, _keyStoreUpdated, Date.now() / 1e3);
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
_keyStore = new WeakMap();
|
|
2004
|
+
_keyStoreUpdated = new WeakMap();
|
|
2005
|
+
|
|
2006
|
+
var __accessCheck$3 = (obj, member, msg) => {
|
|
2007
|
+
if (!member.has(obj))
|
|
2008
|
+
throw TypeError("Cannot " + msg);
|
|
2009
|
+
};
|
|
2010
|
+
var __privateGet$2 = (obj, member, getter) => {
|
|
2011
|
+
__accessCheck$3(obj, member, "read from private field");
|
|
2012
|
+
return getter ? getter.call(obj) : member.get(obj);
|
|
2013
|
+
};
|
|
2014
|
+
var __privateAdd$3 = (obj, member, value) => {
|
|
2015
|
+
if (member.has(obj))
|
|
2016
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
2017
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
2018
|
+
};
|
|
2019
|
+
var __privateSet$2 = (obj, member, value, setter) => {
|
|
2020
|
+
__accessCheck$3(obj, member, "write to private field");
|
|
2021
|
+
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
2022
|
+
return value;
|
|
2023
|
+
};
|
|
2024
|
+
var __privateMethod$3 = (obj, member, method) => {
|
|
2025
|
+
__accessCheck$3(obj, member, "access private method");
|
|
2026
|
+
return method;
|
|
2027
|
+
};
|
|
2028
|
+
var _jwksClient, _algorithms, _getTokenVerificationOptions, getTokenVerificationOptions_fn;
|
|
2029
|
+
class UserTokenHandler {
|
|
2030
|
+
constructor(options) {
|
|
2031
|
+
__privateAdd$3(this, _getTokenVerificationOptions);
|
|
2032
|
+
__privateAdd$3(this, _jwksClient, void 0);
|
|
2033
|
+
__privateAdd$3(this, _algorithms, void 0);
|
|
2034
|
+
__privateSet$2(this, _algorithms, ["ES256"]);
|
|
2035
|
+
__privateSet$2(this, _jwksClient, new JwksClient(async () => {
|
|
2036
|
+
const url = await options.discovery.getBaseUrl("auth");
|
|
2037
|
+
return new URL(`${url}/.well-known/jwks.json`);
|
|
2038
|
+
}));
|
|
2039
|
+
}
|
|
2040
|
+
async verifyToken(token) {
|
|
2041
|
+
const verifyOpts = __privateMethod$3(this, _getTokenVerificationOptions, getTokenVerificationOptions_fn).call(this, token);
|
|
2042
|
+
if (!verifyOpts) {
|
|
2043
|
+
return void 0;
|
|
2044
|
+
}
|
|
2045
|
+
await __privateGet$2(this, _jwksClient).refreshKeyStore(token);
|
|
2046
|
+
const { payload } = await jose.jwtVerify(
|
|
2047
|
+
token,
|
|
2048
|
+
__privateGet$2(this, _jwksClient).getKey,
|
|
2049
|
+
verifyOpts
|
|
2050
|
+
).catch((e) => {
|
|
2051
|
+
throw new errors.AuthenticationError("Invalid token", e);
|
|
2052
|
+
});
|
|
2053
|
+
const userEntityRef = payload.sub;
|
|
2054
|
+
if (!userEntityRef) {
|
|
2055
|
+
throw new errors.AuthenticationError("No user sub found in token");
|
|
2056
|
+
}
|
|
2057
|
+
return { userEntityRef };
|
|
2058
|
+
}
|
|
2059
|
+
createLimitedUserToken(backstageToken) {
|
|
2060
|
+
const [headerRaw, payloadRaw] = backstageToken.split(".");
|
|
2061
|
+
const header = JSON.parse(
|
|
2062
|
+
new TextDecoder().decode(jose.base64url.decode(headerRaw))
|
|
2063
|
+
);
|
|
2064
|
+
const payload = JSON.parse(
|
|
2065
|
+
new TextDecoder().decode(jose.base64url.decode(payloadRaw))
|
|
2066
|
+
);
|
|
2067
|
+
const tokenType = header.typ;
|
|
2068
|
+
if (!tokenType || tokenType === pluginAuthNode.tokenTypes.limitedUser.typParam) {
|
|
2069
|
+
return { token: backstageToken, expiresAt: new Date(payload.exp * 1e3) };
|
|
2070
|
+
}
|
|
2071
|
+
if (tokenType !== pluginAuthNode.tokenTypes.user.typParam) {
|
|
2072
|
+
throw new errors.AuthenticationError(
|
|
2073
|
+
"Failed to create limited user token, invalid token type"
|
|
2074
|
+
);
|
|
2075
|
+
}
|
|
2076
|
+
const limitedUserToken = [
|
|
2077
|
+
jose.base64url.encode(
|
|
2078
|
+
JSON.stringify({
|
|
2079
|
+
typ: pluginAuthNode.tokenTypes.limitedUser.typParam,
|
|
2080
|
+
alg: header.alg,
|
|
2081
|
+
kid: header.kid
|
|
2082
|
+
})
|
|
2083
|
+
),
|
|
2084
|
+
jose.base64url.encode(
|
|
2085
|
+
JSON.stringify({
|
|
2086
|
+
sub: payload.sub,
|
|
2087
|
+
ent: payload.ent,
|
|
2088
|
+
iat: payload.iat,
|
|
2089
|
+
exp: payload.exp
|
|
2090
|
+
})
|
|
2091
|
+
),
|
|
2092
|
+
payload.uip
|
|
2093
|
+
].join(".");
|
|
2094
|
+
return { token: limitedUserToken, expiresAt: new Date(payload.exp * 1e3) };
|
|
2095
|
+
}
|
|
2096
|
+
isLimitedUserToken(token) {
|
|
2097
|
+
try {
|
|
2098
|
+
const { typ } = jose.decodeProtectedHeader(token);
|
|
2099
|
+
return typ === pluginAuthNode.tokenTypes.limitedUser.typParam;
|
|
2100
|
+
} catch {
|
|
2101
|
+
return false;
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
_jwksClient = new WeakMap();
|
|
2106
|
+
_algorithms = new WeakMap();
|
|
2107
|
+
_getTokenVerificationOptions = new WeakSet();
|
|
2108
|
+
getTokenVerificationOptions_fn = function(token) {
|
|
2109
|
+
try {
|
|
2110
|
+
const { typ } = jose.decodeProtectedHeader(token);
|
|
2111
|
+
if (typ === pluginAuthNode.tokenTypes.user.typParam) {
|
|
2112
|
+
return {
|
|
2113
|
+
algorithms: __privateGet$2(this, _algorithms),
|
|
2114
|
+
requiredClaims: ["iat", "exp", "sub"],
|
|
2115
|
+
typ: pluginAuthNode.tokenTypes.user.typParam
|
|
2116
|
+
};
|
|
2117
|
+
}
|
|
2118
|
+
if (typ === pluginAuthNode.tokenTypes.limitedUser.typParam) {
|
|
2119
|
+
return {
|
|
2120
|
+
algorithms: __privateGet$2(this, _algorithms),
|
|
2121
|
+
requiredClaims: ["iat", "exp", "sub"],
|
|
2122
|
+
typ: pluginAuthNode.tokenTypes.limitedUser.typParam
|
|
2123
|
+
};
|
|
2124
|
+
}
|
|
2125
|
+
const { aud } = jose.decodeJwt(token);
|
|
2126
|
+
if (aud === pluginAuthNode.tokenTypes.user.audClaim) {
|
|
2127
|
+
return {
|
|
2128
|
+
algorithms: __privateGet$2(this, _algorithms),
|
|
2129
|
+
audience: pluginAuthNode.tokenTypes.user.audClaim
|
|
2130
|
+
};
|
|
2131
|
+
}
|
|
2132
|
+
} catch {
|
|
2133
|
+
}
|
|
2134
|
+
return void 0;
|
|
2135
|
+
};
|
|
2136
|
+
|
|
2137
|
+
var __defProp = Object.defineProperty;
|
|
2138
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2139
|
+
var __publicField = (obj, key, value) => {
|
|
2140
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2141
|
+
return value;
|
|
2142
|
+
};
|
|
2143
|
+
const KEY_EXPIRATION_MARGIN_FACTOR = 3;
|
|
2144
|
+
const SECONDS_IN_MS = 1e3;
|
|
2145
|
+
const ALLOWED_PLUGIN_ID_PATTERN = /^[a-z0-9_-]+$/i;
|
|
2146
|
+
class PluginTokenHandler {
|
|
2147
|
+
constructor(logger, ownPluginId, publicKeyStore, keyDurationSeconds, algorithm, discovery) {
|
|
2148
|
+
this.logger = logger;
|
|
2149
|
+
this.ownPluginId = ownPluginId;
|
|
2150
|
+
this.publicKeyStore = publicKeyStore;
|
|
2151
|
+
this.keyDurationSeconds = keyDurationSeconds;
|
|
2152
|
+
this.algorithm = algorithm;
|
|
2153
|
+
this.discovery = discovery;
|
|
2154
|
+
__publicField(this, "privateKeyPromise");
|
|
2155
|
+
__publicField(this, "keyExpiry");
|
|
2156
|
+
__publicField(this, "jwksMap", /* @__PURE__ */ new Map());
|
|
2157
|
+
// Tracking state for isTargetPluginSupported
|
|
2158
|
+
__publicField(this, "supportedTargetPlugins", /* @__PURE__ */ new Set());
|
|
2159
|
+
__publicField(this, "targetPluginInflightChecks", /* @__PURE__ */ new Map());
|
|
2160
|
+
}
|
|
2161
|
+
static create(options) {
|
|
2162
|
+
var _a;
|
|
2163
|
+
return new PluginTokenHandler(
|
|
2164
|
+
options.logger,
|
|
2165
|
+
options.ownPluginId,
|
|
2166
|
+
options.publicKeyStore,
|
|
2167
|
+
options.keyDurationSeconds,
|
|
2168
|
+
(_a = options.algorithm) != null ? _a : "ES256",
|
|
2169
|
+
options.discovery
|
|
2170
|
+
);
|
|
2171
|
+
}
|
|
2172
|
+
async verifyToken(token) {
|
|
2173
|
+
try {
|
|
2174
|
+
const { typ } = jose.decodeProtectedHeader(token);
|
|
2175
|
+
if (typ !== pluginAuthNode.tokenTypes.plugin.typParam) {
|
|
2176
|
+
return void 0;
|
|
2177
|
+
}
|
|
2178
|
+
} catch {
|
|
2179
|
+
return void 0;
|
|
2180
|
+
}
|
|
2181
|
+
const pluginId = String(jose.decodeJwt(token).sub);
|
|
2182
|
+
if (!pluginId) {
|
|
2183
|
+
throw new errors.AuthenticationError("Invalid plugin token: missing subject");
|
|
2184
|
+
}
|
|
2185
|
+
if (!ALLOWED_PLUGIN_ID_PATTERN.test(pluginId)) {
|
|
2186
|
+
throw new errors.AuthenticationError(
|
|
2187
|
+
"Invalid plugin token: forbidden subject format"
|
|
2188
|
+
);
|
|
2189
|
+
}
|
|
2190
|
+
const jwksClient = await this.getJwksClient(pluginId);
|
|
2191
|
+
await jwksClient.refreshKeyStore(token);
|
|
2192
|
+
const { payload } = await jose.jwtVerify(
|
|
2193
|
+
token,
|
|
2194
|
+
jwksClient.getKey,
|
|
2195
|
+
{
|
|
2196
|
+
typ: pluginAuthNode.tokenTypes.plugin.typParam,
|
|
2197
|
+
audience: this.ownPluginId,
|
|
2198
|
+
requiredClaims: ["iat", "exp", "sub", "aud"]
|
|
2199
|
+
}
|
|
2200
|
+
).catch((e) => {
|
|
2201
|
+
throw new errors.AuthenticationError("Invalid plugin token", e);
|
|
2202
|
+
});
|
|
2203
|
+
return { subject: `plugin:${payload.sub}`, limitedUserToken: payload.obo };
|
|
2204
|
+
}
|
|
2205
|
+
async issueToken(options) {
|
|
2206
|
+
const { pluginId, targetPluginId, onBehalfOf } = options;
|
|
2207
|
+
const key = await this.getKey();
|
|
2208
|
+
const sub = pluginId;
|
|
2209
|
+
const aud = targetPluginId;
|
|
2210
|
+
const iat = Math.floor(Date.now() / SECONDS_IN_MS);
|
|
2211
|
+
const ourExp = iat + this.keyDurationSeconds;
|
|
2212
|
+
const exp = onBehalfOf ? Math.min(
|
|
2213
|
+
ourExp,
|
|
2214
|
+
Math.floor(onBehalfOf.expiresAt.getTime() / SECONDS_IN_MS)
|
|
2215
|
+
) : ourExp;
|
|
2216
|
+
const claims = { sub, aud, iat, exp, obo: onBehalfOf == null ? void 0 : onBehalfOf.token };
|
|
2217
|
+
const token = await new jose.SignJWT(claims).setProtectedHeader({
|
|
2218
|
+
typ: pluginAuthNode.tokenTypes.plugin.typParam,
|
|
2219
|
+
alg: this.algorithm,
|
|
2220
|
+
kid: key.kid
|
|
2221
|
+
}).setAudience(aud).setSubject(sub).setIssuedAt(iat).setExpirationTime(exp).sign(await jose.importJWK(key));
|
|
2222
|
+
return { token };
|
|
2223
|
+
}
|
|
2224
|
+
async isTargetPluginSupported(targetPluginId) {
|
|
2225
|
+
if (this.supportedTargetPlugins.has(targetPluginId)) {
|
|
2226
|
+
return true;
|
|
2227
|
+
}
|
|
2228
|
+
const inFlight = this.targetPluginInflightChecks.get(targetPluginId);
|
|
2229
|
+
if (inFlight) {
|
|
2230
|
+
return inFlight;
|
|
2231
|
+
}
|
|
2232
|
+
const doCheck = async () => {
|
|
2233
|
+
try {
|
|
2234
|
+
const res = await fetch(
|
|
2235
|
+
`${await this.discovery.getBaseUrl(
|
|
2236
|
+
targetPluginId
|
|
2237
|
+
)}/.backstage/auth/v1/jwks.json`
|
|
2238
|
+
);
|
|
2239
|
+
if (res.status === 404) {
|
|
2240
|
+
return false;
|
|
2241
|
+
}
|
|
2242
|
+
if (!res.ok) {
|
|
2243
|
+
throw new Error(`Failed to fetch jwks.json, ${res.status}`);
|
|
2244
|
+
}
|
|
2245
|
+
const data = await res.json();
|
|
2246
|
+
if (!data.keys) {
|
|
2247
|
+
throw new Error(`Invalid jwks.json response, missing keys`);
|
|
2248
|
+
}
|
|
2249
|
+
this.supportedTargetPlugins.add(targetPluginId);
|
|
2250
|
+
return true;
|
|
2251
|
+
} catch (error) {
|
|
2252
|
+
this.logger.error("Unexpected failure for target JWKS check", error);
|
|
2253
|
+
return false;
|
|
2254
|
+
} finally {
|
|
2255
|
+
this.targetPluginInflightChecks.delete(targetPluginId);
|
|
2256
|
+
}
|
|
2257
|
+
};
|
|
2258
|
+
const check = doCheck();
|
|
2259
|
+
this.targetPluginInflightChecks.set(targetPluginId, check);
|
|
2260
|
+
return check;
|
|
2261
|
+
}
|
|
2262
|
+
async getJwksClient(pluginId) {
|
|
2263
|
+
const client = this.jwksMap.get(pluginId);
|
|
2264
|
+
if (client) {
|
|
2265
|
+
return client;
|
|
2266
|
+
}
|
|
2267
|
+
if (!await this.isTargetPluginSupported(pluginId)) {
|
|
2268
|
+
throw new errors.AuthenticationError(
|
|
2269
|
+
`Received a plugin token where the source '${pluginId}' plugin unexpectedly does not have a JWKS endpoint`
|
|
2270
|
+
);
|
|
2271
|
+
}
|
|
2272
|
+
const newClient = new JwksClient(async () => {
|
|
2273
|
+
return new URL(
|
|
2274
|
+
`${await this.discovery.getBaseUrl(
|
|
2275
|
+
pluginId
|
|
2276
|
+
)}/.backstage/auth/v1/jwks.json`
|
|
2277
|
+
);
|
|
2278
|
+
});
|
|
2279
|
+
this.jwksMap.set(pluginId, newClient);
|
|
2280
|
+
return newClient;
|
|
2281
|
+
}
|
|
2282
|
+
async getKey() {
|
|
2283
|
+
if (this.privateKeyPromise) {
|
|
2284
|
+
if (this.keyExpiry && this.keyExpiry.getTime() > Date.now()) {
|
|
2285
|
+
return this.privateKeyPromise;
|
|
2286
|
+
}
|
|
2287
|
+
this.logger.info(`Signing key has expired, generating new key`);
|
|
2288
|
+
delete this.privateKeyPromise;
|
|
2289
|
+
}
|
|
2290
|
+
this.keyExpiry = new Date(
|
|
2291
|
+
Date.now() + this.keyDurationSeconds * SECONDS_IN_MS
|
|
2292
|
+
);
|
|
2293
|
+
const promise = (async () => {
|
|
2294
|
+
const kid = uuid.v4();
|
|
2295
|
+
const key = await jose.generateKeyPair(this.algorithm);
|
|
2296
|
+
const publicKey = await jose.exportJWK(key.publicKey);
|
|
2297
|
+
const privateKey = await jose.exportJWK(key.privateKey);
|
|
2298
|
+
publicKey.kid = privateKey.kid = kid;
|
|
2299
|
+
publicKey.alg = privateKey.alg = this.algorithm;
|
|
2300
|
+
this.logger.info(`Created new signing key ${kid}`);
|
|
2301
|
+
await this.publicKeyStore.addKey({
|
|
2302
|
+
id: kid,
|
|
2303
|
+
key: publicKey,
|
|
2304
|
+
expiresAt: new Date(
|
|
2305
|
+
Date.now() + this.keyDurationSeconds * SECONDS_IN_MS * KEY_EXPIRATION_MARGIN_FACTOR
|
|
2306
|
+
)
|
|
2307
|
+
});
|
|
2308
|
+
return privateKey;
|
|
2309
|
+
})();
|
|
2310
|
+
this.privateKeyPromise = promise;
|
|
2311
|
+
try {
|
|
2312
|
+
await promise;
|
|
2313
|
+
} catch (error) {
|
|
2314
|
+
this.logger.error(`Failed to generate new signing key, ${error}`);
|
|
2315
|
+
delete this.keyExpiry;
|
|
2316
|
+
delete this.privateKeyPromise;
|
|
2317
|
+
}
|
|
2318
|
+
return promise;
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
const MIGRATIONS_TABLE = "backstage_backend_public_keys__knex_migrations";
|
|
2323
|
+
const TABLE = "backstage_backend_public_keys__keys";
|
|
2324
|
+
function applyDatabaseMigrations(knex) {
|
|
2325
|
+
const migrationsDir = backendCommon.resolvePackagePath(
|
|
2326
|
+
"@backstage/backend-app-api",
|
|
2327
|
+
"migrations"
|
|
2328
|
+
);
|
|
2329
|
+
return knex.migrate.latest({
|
|
2330
|
+
directory: migrationsDir,
|
|
2331
|
+
tableName: MIGRATIONS_TABLE
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2334
|
+
class DatabaseKeyStore {
|
|
2335
|
+
constructor(client, logger) {
|
|
2336
|
+
this.client = client;
|
|
2337
|
+
this.logger = logger;
|
|
2338
|
+
}
|
|
2339
|
+
static async create(options) {
|
|
2340
|
+
var _a;
|
|
2341
|
+
const { database, logger } = options;
|
|
2342
|
+
const client = await database.getClient();
|
|
2343
|
+
if (!((_a = database.migrations) == null ? void 0 : _a.skip)) {
|
|
2344
|
+
await applyDatabaseMigrations(client);
|
|
2345
|
+
}
|
|
2346
|
+
return new DatabaseKeyStore(client, logger);
|
|
2347
|
+
}
|
|
2348
|
+
async addKey(options) {
|
|
2349
|
+
await this.client(TABLE).insert({
|
|
2350
|
+
id: options.key.kid,
|
|
2351
|
+
key: JSON.stringify(options.key),
|
|
2352
|
+
expires_at: options.expiresAt.toISOString()
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
2355
|
+
async listKeys() {
|
|
2356
|
+
const rows = await this.client(TABLE).select();
|
|
2357
|
+
const keys = rows.map((row) => ({
|
|
2358
|
+
id: row.id,
|
|
2359
|
+
key: JSON.parse(row.key),
|
|
2360
|
+
expiresAt: new Date(row.expires_at)
|
|
2361
|
+
}));
|
|
2362
|
+
const validKeys = [];
|
|
2363
|
+
const expiredKeys = [];
|
|
2364
|
+
for (const key of keys) {
|
|
2365
|
+
if (luxon.DateTime.fromJSDate(key.expiresAt) < luxon.DateTime.local()) {
|
|
2366
|
+
expiredKeys.push(key);
|
|
2367
|
+
} else {
|
|
2368
|
+
validKeys.push(key);
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
if (expiredKeys.length > 0) {
|
|
2372
|
+
const kids = expiredKeys.map(({ key }) => key.kid);
|
|
2373
|
+
this.logger.info(
|
|
2374
|
+
`Removing expired plugin service keys, '${kids.join("', '")}'`
|
|
2375
|
+
);
|
|
2376
|
+
this.client(TABLE).delete().whereIn("id", kids).catch((error) => {
|
|
2377
|
+
this.logger.error(
|
|
2378
|
+
"Failed to remove expired plugin service keys",
|
|
2379
|
+
error
|
|
2380
|
+
);
|
|
2381
|
+
});
|
|
2382
|
+
}
|
|
2383
|
+
return { keys: validKeys };
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
|
|
1935
2387
|
var __accessCheck$2 = (obj, member, msg) => {
|
|
1936
2388
|
if (!member.has(obj))
|
|
1937
2389
|
throw TypeError("Cannot " + msg);
|
|
@@ -1991,33 +2443,50 @@ function toInternalBackstageCredentials(credentials) {
|
|
|
1991
2443
|
return internalCredentials;
|
|
1992
2444
|
}
|
|
1993
2445
|
class DefaultAuthService {
|
|
1994
|
-
constructor(tokenManager,
|
|
2446
|
+
constructor(tokenManager, userTokenHandler, pluginId, disableDefaultAuthPolicy, publicKeyStore, pluginTokenHandler) {
|
|
1995
2447
|
this.tokenManager = tokenManager;
|
|
1996
|
-
this.
|
|
2448
|
+
this.userTokenHandler = userTokenHandler;
|
|
1997
2449
|
this.pluginId = pluginId;
|
|
1998
2450
|
this.disableDefaultAuthPolicy = disableDefaultAuthPolicy;
|
|
2451
|
+
this.publicKeyStore = publicKeyStore;
|
|
2452
|
+
this.pluginTokenHandler = pluginTokenHandler;
|
|
1999
2453
|
__privateAdd$2(this, _getJwtExpiration);
|
|
2000
2454
|
}
|
|
2001
2455
|
// allowLimitedAccess is currently ignored, since we currently always use the full user tokens
|
|
2002
2456
|
async authenticate(token) {
|
|
2457
|
+
const pluginResult = await this.pluginTokenHandler.verifyToken(token);
|
|
2458
|
+
if (pluginResult) {
|
|
2459
|
+
if (pluginResult.limitedUserToken) {
|
|
2460
|
+
const userResult2 = await this.userTokenHandler.verifyToken(
|
|
2461
|
+
pluginResult.limitedUserToken
|
|
2462
|
+
);
|
|
2463
|
+
if (!userResult2) {
|
|
2464
|
+
throw new errors.AuthenticationError(
|
|
2465
|
+
"Invalid user token in plugin token obo claim"
|
|
2466
|
+
);
|
|
2467
|
+
}
|
|
2468
|
+
return createCredentialsWithUserPrincipal(
|
|
2469
|
+
userResult2.userEntityRef,
|
|
2470
|
+
pluginResult.limitedUserToken,
|
|
2471
|
+
__privateMethod$2(this, _getJwtExpiration, getJwtExpiration_fn).call(this, pluginResult.limitedUserToken)
|
|
2472
|
+
);
|
|
2473
|
+
}
|
|
2474
|
+
return createCredentialsWithServicePrincipal(pluginResult.subject);
|
|
2475
|
+
}
|
|
2476
|
+
const userResult = await this.userTokenHandler.verifyToken(token);
|
|
2477
|
+
if (userResult) {
|
|
2478
|
+
return createCredentialsWithUserPrincipal(
|
|
2479
|
+
userResult.userEntityRef,
|
|
2480
|
+
token,
|
|
2481
|
+
__privateMethod$2(this, _getJwtExpiration, getJwtExpiration_fn).call(this, token)
|
|
2482
|
+
);
|
|
2483
|
+
}
|
|
2003
2484
|
const { sub, aud } = jose.decodeJwt(token);
|
|
2004
2485
|
if (sub === "backstage-server" && !aud) {
|
|
2005
2486
|
await this.tokenManager.authenticate(token);
|
|
2006
2487
|
return createCredentialsWithServicePrincipal("external:backstage-plugin");
|
|
2007
2488
|
}
|
|
2008
|
-
|
|
2009
|
-
request: {
|
|
2010
|
-
headers: { authorization: `Bearer ${token}` }
|
|
2011
|
-
}
|
|
2012
|
-
});
|
|
2013
|
-
if (!identity) {
|
|
2014
|
-
throw new errors.AuthenticationError("Invalid user token");
|
|
2015
|
-
}
|
|
2016
|
-
return createCredentialsWithUserPrincipal(
|
|
2017
|
-
identity.identity.userEntityRef,
|
|
2018
|
-
token,
|
|
2019
|
-
__privateMethod$2(this, _getJwtExpiration, getJwtExpiration_fn).call(this, token)
|
|
2020
|
-
);
|
|
2489
|
+
throw new errors.AuthenticationError("Unknown token");
|
|
2021
2490
|
}
|
|
2022
2491
|
isPrincipal(credentials, type) {
|
|
2023
2492
|
const principal = credentials.principal;
|
|
@@ -2036,19 +2505,44 @@ class DefaultAuthService {
|
|
|
2036
2505
|
return createCredentialsWithServicePrincipal(`plugin:${this.pluginId}`);
|
|
2037
2506
|
}
|
|
2038
2507
|
async getPluginRequestToken(options) {
|
|
2508
|
+
const { targetPluginId } = options;
|
|
2039
2509
|
const internalForward = toInternalBackstageCredentials(options.onBehalfOf);
|
|
2040
2510
|
const { type } = internalForward.principal;
|
|
2041
2511
|
if (type === "none" && this.disableDefaultAuthPolicy) {
|
|
2042
2512
|
return { token: "" };
|
|
2043
2513
|
}
|
|
2514
|
+
const targetSupportsNewAuth = await this.pluginTokenHandler.isTargetPluginSupported(targetPluginId);
|
|
2044
2515
|
switch (type) {
|
|
2045
2516
|
case "service":
|
|
2517
|
+
if (targetSupportsNewAuth) {
|
|
2518
|
+
return this.pluginTokenHandler.issueToken({
|
|
2519
|
+
pluginId: this.pluginId,
|
|
2520
|
+
targetPluginId
|
|
2521
|
+
});
|
|
2522
|
+
}
|
|
2046
2523
|
return this.tokenManager.getToken();
|
|
2047
|
-
case "user":
|
|
2048
|
-
|
|
2524
|
+
case "user": {
|
|
2525
|
+
const { token } = internalForward;
|
|
2526
|
+
if (!token) {
|
|
2049
2527
|
throw new Error("User credentials is unexpectedly missing token");
|
|
2050
2528
|
}
|
|
2051
|
-
|
|
2529
|
+
if (targetSupportsNewAuth) {
|
|
2530
|
+
const onBehalfOf = await this.userTokenHandler.createLimitedUserToken(
|
|
2531
|
+
token
|
|
2532
|
+
);
|
|
2533
|
+
return this.pluginTokenHandler.issueToken({
|
|
2534
|
+
pluginId: this.pluginId,
|
|
2535
|
+
targetPluginId,
|
|
2536
|
+
onBehalfOf
|
|
2537
|
+
});
|
|
2538
|
+
}
|
|
2539
|
+
if (this.userTokenHandler.isLimitedUserToken(token)) {
|
|
2540
|
+
throw new errors.AuthenticationError(
|
|
2541
|
+
`Unable to call '${targetPluginId}' plugin on behalf of user, because the target plugin does not support on-behalf-of tokens`
|
|
2542
|
+
);
|
|
2543
|
+
}
|
|
2544
|
+
return { token };
|
|
2545
|
+
}
|
|
2052
2546
|
default:
|
|
2053
2547
|
throw new errors.AuthenticationError(
|
|
2054
2548
|
`Refused to issue service token for credential type '${type}'`
|
|
@@ -2056,14 +2550,17 @@ class DefaultAuthService {
|
|
|
2056
2550
|
}
|
|
2057
2551
|
}
|
|
2058
2552
|
async getLimitedUserToken(credentials) {
|
|
2059
|
-
const
|
|
2060
|
-
|
|
2061
|
-
if (!token) {
|
|
2553
|
+
const { token: backstageToken } = toInternalBackstageCredentials(credentials);
|
|
2554
|
+
if (!backstageToken) {
|
|
2062
2555
|
throw new errors.AuthenticationError(
|
|
2063
2556
|
"User credentials is unexpectedly missing token"
|
|
2064
2557
|
);
|
|
2065
2558
|
}
|
|
2066
|
-
return
|
|
2559
|
+
return this.userTokenHandler.createLimitedUserToken(backstageToken);
|
|
2560
|
+
}
|
|
2561
|
+
async listPublicServiceKeys() {
|
|
2562
|
+
const { keys } = await this.publicKeyStore.listKeys();
|
|
2563
|
+
return { keys: keys.map(({ key }) => key) };
|
|
2067
2564
|
}
|
|
2068
2565
|
}
|
|
2069
2566
|
_getJwtExpiration = new WeakSet();
|
|
@@ -2079,25 +2576,35 @@ const authServiceFactory = backendPluginApi.createServiceFactory({
|
|
|
2079
2576
|
deps: {
|
|
2080
2577
|
config: backendPluginApi.coreServices.rootConfig,
|
|
2081
2578
|
logger: backendPluginApi.coreServices.rootLogger,
|
|
2579
|
+
discovery: backendPluginApi.coreServices.discovery,
|
|
2082
2580
|
plugin: backendPluginApi.coreServices.pluginMetadata,
|
|
2083
|
-
|
|
2581
|
+
database: backendPluginApi.coreServices.database,
|
|
2084
2582
|
// Re-using the token manager makes sure that we use the same generated keys for
|
|
2085
2583
|
// development as plugins that have not yet been migrated. It's important that this
|
|
2086
2584
|
// keeps working as long as there are plugins that have not been migrated to the
|
|
2087
2585
|
// new auth services in the new backend system.
|
|
2088
2586
|
tokenManager: backendPluginApi.coreServices.tokenManager
|
|
2089
2587
|
},
|
|
2090
|
-
async factory({ config,
|
|
2588
|
+
async factory({ config, discovery, plugin, tokenManager, logger, database }) {
|
|
2091
2589
|
const disableDefaultAuthPolicy = Boolean(
|
|
2092
2590
|
config.getOptionalBoolean(
|
|
2093
2591
|
"backend.auth.dangerouslyDisableDefaultAuthPolicy"
|
|
2094
2592
|
)
|
|
2095
2593
|
);
|
|
2594
|
+
const publicKeyStore = await DatabaseKeyStore.create({ database, logger });
|
|
2096
2595
|
return new DefaultAuthService(
|
|
2097
2596
|
tokenManager,
|
|
2098
|
-
|
|
2597
|
+
new UserTokenHandler({ discovery }),
|
|
2099
2598
|
plugin.getId(),
|
|
2100
|
-
disableDefaultAuthPolicy
|
|
2599
|
+
disableDefaultAuthPolicy,
|
|
2600
|
+
publicKeyStore,
|
|
2601
|
+
PluginTokenHandler.create({
|
|
2602
|
+
ownPluginId: plugin.getId(),
|
|
2603
|
+
keyDurationSeconds: 60 * 60,
|
|
2604
|
+
logger,
|
|
2605
|
+
publicKeyStore,
|
|
2606
|
+
discovery
|
|
2607
|
+
})
|
|
2101
2608
|
);
|
|
2102
2609
|
}
|
|
2103
2610
|
});
|
|
@@ -2269,7 +2776,7 @@ var __privateMethod$1 = (obj, member, method) => {
|
|
|
2269
2776
|
__accessCheck$1(obj, member, "access private method");
|
|
2270
2777
|
return method;
|
|
2271
2778
|
};
|
|
2272
|
-
var _auth, _discovery, _pluginId, _extractCredentialsFromRequest, extractCredentialsFromRequest_fn, _extractLimitedCredentialsFromRequest, extractLimitedCredentialsFromRequest_fn, _getCredentials, getCredentials_fn, _getLimitedCredentials, getLimitedCredentials_fn, _existingCookieExpiration, existingCookieExpiration_fn;
|
|
2779
|
+
var _auth, _discovery, _pluginId, _extractCredentialsFromRequest, extractCredentialsFromRequest_fn, _extractLimitedCredentialsFromRequest, extractLimitedCredentialsFromRequest_fn, _getCredentials, getCredentials_fn, _getLimitedCredentials, getLimitedCredentials_fn, _getCookieOptions, getCookieOptions_fn, _existingCookieExpiration, existingCookieExpiration_fn;
|
|
2273
2780
|
const FIVE_MINUTES_MS = 5 * 60 * 1e3;
|
|
2274
2781
|
const BACKSTAGE_AUTH_COOKIE = "backstage-auth";
|
|
2275
2782
|
function getTokenFromRequest(req) {
|
|
@@ -2305,6 +2812,7 @@ class DefaultHttpAuthService {
|
|
|
2305
2812
|
__privateAdd$1(this, _extractLimitedCredentialsFromRequest);
|
|
2306
2813
|
__privateAdd$1(this, _getCredentials);
|
|
2307
2814
|
__privateAdd$1(this, _getLimitedCredentials);
|
|
2815
|
+
__privateAdd$1(this, _getCookieOptions);
|
|
2308
2816
|
__privateAdd$1(this, _existingCookieExpiration);
|
|
2309
2817
|
__privateAdd$1(this, _auth, void 0);
|
|
2310
2818
|
__privateAdd$1(this, _discovery, void 0);
|
|
@@ -2349,6 +2857,13 @@ class DefaultHttpAuthService {
|
|
|
2349
2857
|
}
|
|
2350
2858
|
let credentials;
|
|
2351
2859
|
if (options == null ? void 0 : options.credentials) {
|
|
2860
|
+
if (__privateGet$1(this, _auth).isPrincipal(options.credentials, "none")) {
|
|
2861
|
+
res.clearCookie(
|
|
2862
|
+
BACKSTAGE_AUTH_COOKIE,
|
|
2863
|
+
await __privateMethod$1(this, _getCookieOptions, getCookieOptions_fn).call(this, res.req)
|
|
2864
|
+
);
|
|
2865
|
+
return { expiresAt: /* @__PURE__ */ new Date() };
|
|
2866
|
+
}
|
|
2352
2867
|
if (!__privateGet$1(this, _auth).isPrincipal(options.credentials, "user")) {
|
|
2353
2868
|
throw new errors.AuthenticationError(
|
|
2354
2869
|
"Refused to issue cookie for non-user principal"
|
|
@@ -2362,26 +2877,15 @@ class DefaultHttpAuthService {
|
|
|
2362
2877
|
if (existingExpiresAt && !willExpireSoon(existingExpiresAt)) {
|
|
2363
2878
|
return { expiresAt: existingExpiresAt };
|
|
2364
2879
|
}
|
|
2365
|
-
const originHeader = res.req.headers.origin;
|
|
2366
|
-
const origin = !originHeader || originHeader === "null" ? void 0 : originHeader;
|
|
2367
|
-
const externalBaseUrlStr = await __privateGet$1(this, _discovery).getExternalBaseUrl(
|
|
2368
|
-
__privateGet$1(this, _pluginId)
|
|
2369
|
-
);
|
|
2370
|
-
const externalBaseUrl = new URL(origin != null ? origin : externalBaseUrlStr);
|
|
2371
2880
|
const { token, expiresAt } = await __privateGet$1(this, _auth).getLimitedUserToken(
|
|
2372
2881
|
credentials
|
|
2373
2882
|
);
|
|
2374
2883
|
if (!token) {
|
|
2375
2884
|
throw new Error("User credentials is unexpectedly missing token");
|
|
2376
2885
|
}
|
|
2377
|
-
const secure = externalBaseUrl.protocol === "https:" || externalBaseUrl.hostname === "localhost";
|
|
2378
2886
|
res.cookie(BACKSTAGE_AUTH_COOKIE, token, {
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
expires: expiresAt,
|
|
2382
|
-
secure,
|
|
2383
|
-
priority: "high",
|
|
2384
|
-
sameSite: secure ? "none" : "lax"
|
|
2887
|
+
...await __privateMethod$1(this, _getCookieOptions, getCookieOptions_fn).call(this, res.req),
|
|
2888
|
+
expires: expiresAt
|
|
2385
2889
|
});
|
|
2386
2890
|
return { expiresAt };
|
|
2387
2891
|
}
|
|
@@ -2423,6 +2927,23 @@ getLimitedCredentials_fn = async function(req) {
|
|
|
2423
2927
|
var _a;
|
|
2424
2928
|
return (_a = req[limitedCredentialsSymbol]) != null ? _a : req[limitedCredentialsSymbol] = __privateMethod$1(this, _extractLimitedCredentialsFromRequest, extractLimitedCredentialsFromRequest_fn).call(this, req);
|
|
2425
2929
|
};
|
|
2930
|
+
_getCookieOptions = new WeakSet();
|
|
2931
|
+
getCookieOptions_fn = async function(req) {
|
|
2932
|
+
const originHeader = req.headers.origin;
|
|
2933
|
+
const origin = !originHeader || originHeader === "null" ? void 0 : originHeader;
|
|
2934
|
+
const externalBaseUrlStr = await __privateGet$1(this, _discovery).getExternalBaseUrl(
|
|
2935
|
+
__privateGet$1(this, _pluginId)
|
|
2936
|
+
);
|
|
2937
|
+
const externalBaseUrl = new URL(origin != null ? origin : externalBaseUrlStr);
|
|
2938
|
+
const secure = externalBaseUrl.protocol === "https:" || externalBaseUrl.hostname === "localhost";
|
|
2939
|
+
return {
|
|
2940
|
+
domain: externalBaseUrl.hostname,
|
|
2941
|
+
httpOnly: true,
|
|
2942
|
+
secure,
|
|
2943
|
+
priority: "high",
|
|
2944
|
+
sameSite: secure ? "none" : "lax"
|
|
2945
|
+
};
|
|
2946
|
+
};
|
|
2426
2947
|
_existingCookieExpiration = new WeakSet();
|
|
2427
2948
|
existingCookieExpiration_fn = async function(req) {
|
|
2428
2949
|
const existingCookie = getCookieFromRequest(req);
|
|
@@ -2559,25 +3080,71 @@ function createCredentialsBarrier(options) {
|
|
|
2559
3080
|
return { middleware, addAuthPolicy };
|
|
2560
3081
|
}
|
|
2561
3082
|
|
|
3083
|
+
function createAuthIntegrationRouter(options) {
|
|
3084
|
+
const router = Router__default.default();
|
|
3085
|
+
router.get("/.backstage/auth/v1/jwks.json", async (_req, res) => {
|
|
3086
|
+
const { keys } = await options.auth.listPublicServiceKeys();
|
|
3087
|
+
res.json({ keys });
|
|
3088
|
+
});
|
|
3089
|
+
return router;
|
|
3090
|
+
}
|
|
3091
|
+
|
|
3092
|
+
const WELL_KNOWN_COOKIE_PATH_V1 = "/.backstage/auth/v1/cookie";
|
|
3093
|
+
function createCookieAuthRefreshMiddleware(options) {
|
|
3094
|
+
const { auth, httpAuth } = options;
|
|
3095
|
+
const router = Router__default.default();
|
|
3096
|
+
router.get(WELL_KNOWN_COOKIE_PATH_V1, async (_, res) => {
|
|
3097
|
+
const { expiresAt } = await httpAuth.issueUserCookie(res);
|
|
3098
|
+
res.json({ expiresAt: expiresAt.toISOString() });
|
|
3099
|
+
});
|
|
3100
|
+
router.delete(WELL_KNOWN_COOKIE_PATH_V1, async (_, res) => {
|
|
3101
|
+
const credentials = await auth.getNoneCredentials();
|
|
3102
|
+
await httpAuth.issueUserCookie(res, { credentials });
|
|
3103
|
+
res.status(204).end();
|
|
3104
|
+
});
|
|
3105
|
+
return router;
|
|
3106
|
+
}
|
|
3107
|
+
|
|
2562
3108
|
const httpRouterServiceFactory = backendPluginApi.createServiceFactory(
|
|
2563
3109
|
(options) => ({
|
|
2564
3110
|
service: backendPluginApi.coreServices.httpRouter,
|
|
3111
|
+
initialization: "always",
|
|
2565
3112
|
deps: {
|
|
2566
3113
|
plugin: backendPluginApi.coreServices.pluginMetadata,
|
|
2567
3114
|
config: backendPluginApi.coreServices.rootConfig,
|
|
3115
|
+
logger: backendPluginApi.coreServices.logger,
|
|
2568
3116
|
lifecycle: backendPluginApi.coreServices.lifecycle,
|
|
2569
3117
|
rootHttpRouter: backendPluginApi.coreServices.rootHttpRouter,
|
|
3118
|
+
auth: backendPluginApi.coreServices.auth,
|
|
2570
3119
|
httpAuth: backendPluginApi.coreServices.httpAuth
|
|
2571
3120
|
},
|
|
2572
|
-
async factory({
|
|
3121
|
+
async factory({
|
|
3122
|
+
auth,
|
|
3123
|
+
httpAuth,
|
|
3124
|
+
config,
|
|
3125
|
+
logger,
|
|
3126
|
+
plugin,
|
|
3127
|
+
rootHttpRouter,
|
|
3128
|
+
lifecycle
|
|
3129
|
+
}) {
|
|
2573
3130
|
var _a;
|
|
3131
|
+
if (options == null ? void 0 : options.getPath) {
|
|
3132
|
+
logger.warn(
|
|
3133
|
+
`DEPRECATION WARNING: The 'getPath' option for HttpRouterService is deprecated. The ability to reconfigure the '/api/' path prefix for plugins will be removed in the future.`
|
|
3134
|
+
);
|
|
3135
|
+
}
|
|
2574
3136
|
const getPath = (_a = options == null ? void 0 : options.getPath) != null ? _a : (id) => `/api/${id}`;
|
|
2575
3137
|
const path = getPath(plugin.getId());
|
|
2576
|
-
const router =
|
|
3138
|
+
const router = Router__default.default();
|
|
2577
3139
|
rootHttpRouter.use(path, router);
|
|
2578
|
-
const credentialsBarrier = createCredentialsBarrier({
|
|
3140
|
+
const credentialsBarrier = createCredentialsBarrier({
|
|
3141
|
+
httpAuth,
|
|
3142
|
+
config
|
|
3143
|
+
});
|
|
2579
3144
|
router.use(createLifecycleMiddleware({ lifecycle }));
|
|
3145
|
+
router.use(createAuthIntegrationRouter({ auth }));
|
|
2580
3146
|
router.use(credentialsBarrier.middleware);
|
|
3147
|
+
router.use(createCookieAuthRefreshMiddleware({ auth, httpAuth }));
|
|
2581
3148
|
return {
|
|
2582
3149
|
use(handler) {
|
|
2583
3150
|
router.use(handler);
|
|
@@ -2666,6 +3233,9 @@ const _DefaultRootHttpRouter = class _DefaultRootHttpRouter {
|
|
|
2666
3233
|
__privateAdd(this, _existingPaths, new Array());
|
|
2667
3234
|
__privateSet(this, _indexPath, indexPath);
|
|
2668
3235
|
__privateGet(this, _router).use(__privateGet(this, _namedRoutes));
|
|
3236
|
+
__privateGet(this, _router).use("/api/", (_req, _res, next) => {
|
|
3237
|
+
next("router");
|
|
3238
|
+
});
|
|
2669
3239
|
if (__privateGet(this, _indexPath)) {
|
|
2670
3240
|
__privateGet(this, _router).use(__privateGet(this, _indexRouter));
|
|
2671
3241
|
}
|