@supertokens-plugins/rownd-nodejs 0.2.0 → 0.3.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/dist/bulkMigrate.js +1096 -0
- package/dist/cli.js +54 -0
- package/dist/generateAppConfig.js +731 -0
- package/dist/index.d.mts +826 -0
- package/dist/index.d.ts +826 -0
- package/dist/index.js +2752 -0
- package/dist/index.mjs +2732 -0
- package/dist/initConfig.js +136 -0
- package/dist/setupCoreInstance.js +295 -0
- package/package.json +13 -10
- package/scripts/bulkMigrate.ts +0 -450
- package/scripts/config.yaml +0 -27
- package/src/constants.ts +0 -5
- package/src/errors.ts +0 -13
- package/src/index.ts +0 -7
- package/src/logger.ts +0 -7
- package/src/plugin.test.ts +0 -790
- package/src/plugin.ts +0 -189
- package/src/pluginImplementation.ts +0 -187
- package/src/telemetry/axiomTelemetryClient.ts +0 -34
- package/src/telemetry/createTelemetryClient.ts +0 -87
- package/src/telemetry/openTelemetryClient.ts +0 -32
- package/src/types.ts +0 -124
package/dist/index.js
ADDED
|
@@ -0,0 +1,2752 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
11
|
+
var __export = (target, all) => {
|
|
12
|
+
for (var name in all)
|
|
13
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
|
+
};
|
|
15
|
+
var __copyProps = (to, from, except, desc) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
17
|
+
for (let key of __getOwnPropNames(from))
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
+
mod
|
|
30
|
+
));
|
|
31
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
|
+
|
|
33
|
+
// ../../node_modules/supertokens-js-override/lib/build/getProxyObject.js
|
|
34
|
+
var require_getProxyObject = __commonJS({
|
|
35
|
+
"../../node_modules/supertokens-js-override/lib/build/getProxyObject.js"(exports2) {
|
|
36
|
+
"use strict";
|
|
37
|
+
var __assign = exports2 && exports2.__assign || function() {
|
|
38
|
+
__assign = Object.assign || function(t) {
|
|
39
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
40
|
+
s = arguments[i];
|
|
41
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
42
|
+
t[p] = s[p];
|
|
43
|
+
}
|
|
44
|
+
return t;
|
|
45
|
+
};
|
|
46
|
+
return __assign.apply(this, arguments);
|
|
47
|
+
};
|
|
48
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
49
|
+
exports2.getProxyObject = void 0;
|
|
50
|
+
function getProxyObject(orig) {
|
|
51
|
+
var ret = __assign(__assign({}, orig), { _call: function(_, __) {
|
|
52
|
+
throw new Error("This function should only be called through the recipe object");
|
|
53
|
+
} });
|
|
54
|
+
var keys = Object.keys(ret);
|
|
55
|
+
var _loop_1 = function(k2) {
|
|
56
|
+
if (k2 !== "_call") {
|
|
57
|
+
ret[k2] = function() {
|
|
58
|
+
var args = [];
|
|
59
|
+
for (var _i2 = 0; _i2 < arguments.length; _i2++) {
|
|
60
|
+
args[_i2] = arguments[_i2];
|
|
61
|
+
}
|
|
62
|
+
return this._call(k2, args);
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
|
|
67
|
+
var k = keys_1[_i];
|
|
68
|
+
_loop_1(k);
|
|
69
|
+
}
|
|
70
|
+
return ret;
|
|
71
|
+
}
|
|
72
|
+
exports2.getProxyObject = getProxyObject;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// ../../node_modules/supertokens-js-override/lib/build/index.js
|
|
77
|
+
var require_build = __commonJS({
|
|
78
|
+
"../../node_modules/supertokens-js-override/lib/build/index.js"(exports2) {
|
|
79
|
+
"use strict";
|
|
80
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
81
|
+
exports2.OverrideableBuilder = void 0;
|
|
82
|
+
var getProxyObject_1 = require_getProxyObject();
|
|
83
|
+
var OverrideableBuilder2 = (
|
|
84
|
+
/** @class */
|
|
85
|
+
(function() {
|
|
86
|
+
function OverrideableBuilder3(originalImplementation) {
|
|
87
|
+
this.layers = [originalImplementation];
|
|
88
|
+
this.proxies = [];
|
|
89
|
+
}
|
|
90
|
+
OverrideableBuilder3.prototype.override = function(overrideFunc) {
|
|
91
|
+
var proxy = (0, getProxyObject_1.getProxyObject)(this.layers[0]);
|
|
92
|
+
var layer = overrideFunc(proxy, this);
|
|
93
|
+
for (var _i = 0, _a = Object.keys(this.layers[0]); _i < _a.length; _i++) {
|
|
94
|
+
var key = _a[_i];
|
|
95
|
+
if (layer[key] === proxy[key] || key === "_call") {
|
|
96
|
+
delete layer[key];
|
|
97
|
+
} else if (layer[key] === void 0) {
|
|
98
|
+
layer[key] = null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
this.layers.push(layer);
|
|
102
|
+
this.proxies.push(proxy);
|
|
103
|
+
return this;
|
|
104
|
+
};
|
|
105
|
+
OverrideableBuilder3.prototype.build = function() {
|
|
106
|
+
var _this = this;
|
|
107
|
+
if (this.result) {
|
|
108
|
+
return this.result;
|
|
109
|
+
}
|
|
110
|
+
this.result = {};
|
|
111
|
+
for (var _i = 0, _a = this.layers; _i < _a.length; _i++) {
|
|
112
|
+
var layer = _a[_i];
|
|
113
|
+
for (var _b = 0, _c = Object.keys(layer); _b < _c.length; _b++) {
|
|
114
|
+
var key = _c[_b];
|
|
115
|
+
var override = layer[key];
|
|
116
|
+
if (override !== void 0) {
|
|
117
|
+
if (override === null) {
|
|
118
|
+
this.result[key] = void 0;
|
|
119
|
+
} else if (typeof override === "function") {
|
|
120
|
+
this.result[key] = override.bind(this.result);
|
|
121
|
+
} else {
|
|
122
|
+
this.result[key] = override;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
var _loop_1 = function(proxyInd2) {
|
|
128
|
+
var proxy = this_1.proxies[proxyInd2];
|
|
129
|
+
proxy._call = function(fname, args) {
|
|
130
|
+
for (var i = proxyInd2; i >= 0; --i) {
|
|
131
|
+
var func = _this.layers[i][fname];
|
|
132
|
+
if (func !== void 0 && func !== null) {
|
|
133
|
+
return func.bind(_this.result).apply(void 0, args);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
var this_1 = this;
|
|
139
|
+
for (var proxyInd = 0; proxyInd < this.proxies.length; ++proxyInd) {
|
|
140
|
+
_loop_1(proxyInd);
|
|
141
|
+
}
|
|
142
|
+
return this.result;
|
|
143
|
+
};
|
|
144
|
+
return OverrideableBuilder3;
|
|
145
|
+
})()
|
|
146
|
+
);
|
|
147
|
+
exports2.OverrideableBuilder = OverrideableBuilder2;
|
|
148
|
+
exports2.default = OverrideableBuilder2;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// ../../node_modules/has-flag/index.js
|
|
153
|
+
var require_has_flag = __commonJS({
|
|
154
|
+
"../../node_modules/has-flag/index.js"(exports2, module2) {
|
|
155
|
+
"use strict";
|
|
156
|
+
module2.exports = (flag, argv = process.argv) => {
|
|
157
|
+
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
158
|
+
const position = argv.indexOf(prefix + flag);
|
|
159
|
+
const terminatorPosition = argv.indexOf("--");
|
|
160
|
+
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// ../../node_modules/supports-color/index.js
|
|
166
|
+
var require_supports_color = __commonJS({
|
|
167
|
+
"../../node_modules/supports-color/index.js"(exports2, module2) {
|
|
168
|
+
"use strict";
|
|
169
|
+
var os = require("os");
|
|
170
|
+
var tty = require("tty");
|
|
171
|
+
var hasFlag = require_has_flag();
|
|
172
|
+
var { env } = process;
|
|
173
|
+
var forceColor;
|
|
174
|
+
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
175
|
+
forceColor = 0;
|
|
176
|
+
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
177
|
+
forceColor = 1;
|
|
178
|
+
}
|
|
179
|
+
if ("FORCE_COLOR" in env) {
|
|
180
|
+
if (env.FORCE_COLOR === "true") {
|
|
181
|
+
forceColor = 1;
|
|
182
|
+
} else if (env.FORCE_COLOR === "false") {
|
|
183
|
+
forceColor = 0;
|
|
184
|
+
} else {
|
|
185
|
+
forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function translateLevel(level) {
|
|
189
|
+
if (level === 0) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
level,
|
|
194
|
+
hasBasic: true,
|
|
195
|
+
has256: level >= 2,
|
|
196
|
+
has16m: level >= 3
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function supportsColor(haveStream, streamIsTTY) {
|
|
200
|
+
if (forceColor === 0) {
|
|
201
|
+
return 0;
|
|
202
|
+
}
|
|
203
|
+
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
204
|
+
return 3;
|
|
205
|
+
}
|
|
206
|
+
if (hasFlag("color=256")) {
|
|
207
|
+
return 2;
|
|
208
|
+
}
|
|
209
|
+
if (haveStream && !streamIsTTY && forceColor === void 0) {
|
|
210
|
+
return 0;
|
|
211
|
+
}
|
|
212
|
+
const min = forceColor || 0;
|
|
213
|
+
if (env.TERM === "dumb") {
|
|
214
|
+
return min;
|
|
215
|
+
}
|
|
216
|
+
if (process.platform === "win32") {
|
|
217
|
+
const osRelease = os.release().split(".");
|
|
218
|
+
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
219
|
+
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
220
|
+
}
|
|
221
|
+
return 1;
|
|
222
|
+
}
|
|
223
|
+
if ("CI" in env) {
|
|
224
|
+
if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
|
|
225
|
+
return 1;
|
|
226
|
+
}
|
|
227
|
+
return min;
|
|
228
|
+
}
|
|
229
|
+
if ("TEAMCITY_VERSION" in env) {
|
|
230
|
+
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
231
|
+
}
|
|
232
|
+
if (env.COLORTERM === "truecolor") {
|
|
233
|
+
return 3;
|
|
234
|
+
}
|
|
235
|
+
if ("TERM_PROGRAM" in env) {
|
|
236
|
+
const version = parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
237
|
+
switch (env.TERM_PROGRAM) {
|
|
238
|
+
case "iTerm.app":
|
|
239
|
+
return version >= 3 ? 3 : 2;
|
|
240
|
+
case "Apple_Terminal":
|
|
241
|
+
return 2;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (/-256(color)?$/i.test(env.TERM)) {
|
|
245
|
+
return 2;
|
|
246
|
+
}
|
|
247
|
+
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|
248
|
+
return 1;
|
|
249
|
+
}
|
|
250
|
+
if ("COLORTERM" in env) {
|
|
251
|
+
return 1;
|
|
252
|
+
}
|
|
253
|
+
return min;
|
|
254
|
+
}
|
|
255
|
+
function getSupportLevel(stream) {
|
|
256
|
+
const level = supportsColor(stream, stream && stream.isTTY);
|
|
257
|
+
return translateLevel(level);
|
|
258
|
+
}
|
|
259
|
+
module2.exports = {
|
|
260
|
+
supportsColor: getSupportLevel,
|
|
261
|
+
stdout: translateLevel(supportsColor(true, tty.isatty(1))),
|
|
262
|
+
stderr: translateLevel(supportsColor(true, tty.isatty(2)))
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// src/index.ts
|
|
268
|
+
var index_exports = {};
|
|
269
|
+
__export(index_exports, {
|
|
270
|
+
ANONYMOUS_AUTH_METHOD_ID: () => ANONYMOUS_AUTH_METHOD_ID,
|
|
271
|
+
DEFAULT_ROWND_SCHEMA: () => DEFAULT_ROWND_SCHEMA,
|
|
272
|
+
GUEST_AUTH_METHOD_ID: () => GUEST_AUTH_METHOD_ID,
|
|
273
|
+
HANDLE_BASE_PATH: () => HANDLE_BASE_PATH,
|
|
274
|
+
PLUGIN_ID: () => PLUGIN_ID,
|
|
275
|
+
PLUGIN_SDK_VERSION: () => PLUGIN_SDK_VERSION,
|
|
276
|
+
PUBLIC_TENANT_ID: () => PUBLIC_TENANT_ID,
|
|
277
|
+
ROWND_JWT_CLAIMS: () => ROWND_JWT_CLAIMS,
|
|
278
|
+
ROWND_PLUGIN_ERROR_MESSAGES: () => ROWND_PLUGIN_ERROR_MESSAGES,
|
|
279
|
+
RowndPluginError: () => RowndPluginError,
|
|
280
|
+
default: () => index_default,
|
|
281
|
+
getRowndClient: () => getRowndClient,
|
|
282
|
+
init: () => init,
|
|
283
|
+
setRowndClient: () => setRowndClient
|
|
284
|
+
});
|
|
285
|
+
module.exports = __toCommonJS(index_exports);
|
|
286
|
+
|
|
287
|
+
// ../../shared/js/src/createPluginInit.ts
|
|
288
|
+
var import_supertokens_js_override = __toESM(require_build());
|
|
289
|
+
var createPluginInitFunction = (init2, getImplementation, getNormalisedConfig = (config2) => config2) => {
|
|
290
|
+
const getNormalizedImplementation = typeof getImplementation === "function" ? getImplementation : (_config) => getImplementation || {};
|
|
291
|
+
return (inputConfig) => {
|
|
292
|
+
const config2 = getNormalisedConfig(inputConfig || {});
|
|
293
|
+
const baseImplementation = getNormalizedImplementation(config2);
|
|
294
|
+
const overrideBuilder = new import_supertokens_js_override.OverrideableBuilder(baseImplementation);
|
|
295
|
+
if (inputConfig?.override) {
|
|
296
|
+
overrideBuilder.override(inputConfig.override);
|
|
297
|
+
}
|
|
298
|
+
const actualImplementation = overrideBuilder.build();
|
|
299
|
+
return init2(config2, actualImplementation);
|
|
300
|
+
};
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
// ../../shared/nodejs/src/pluginUserMetadata.ts
|
|
304
|
+
var import_usermetadata = __toESM(require("supertokens-node/recipe/usermetadata"));
|
|
305
|
+
|
|
306
|
+
// ../../shared/nodejs/src/withRequestHandler.ts
|
|
307
|
+
var withRequestHandler = (fn) => {
|
|
308
|
+
return async (req, res, session, userContext) => {
|
|
309
|
+
const result = await fn(req, res, session, userContext);
|
|
310
|
+
if (result.status === "OK") {
|
|
311
|
+
res.setStatusCode(200);
|
|
312
|
+
} else {
|
|
313
|
+
res.setStatusCode(Number(result.code) || 400);
|
|
314
|
+
}
|
|
315
|
+
res.sendJSONResponse(result);
|
|
316
|
+
return null;
|
|
317
|
+
};
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
// ../../shared/nodejs/src/log/logger.ts
|
|
321
|
+
var import_util = __toESM(require("util"));
|
|
322
|
+
|
|
323
|
+
// ../../shared/nodejs/src/log/common.ts
|
|
324
|
+
function setup(env) {
|
|
325
|
+
createDebug.debug = createDebug;
|
|
326
|
+
createDebug.default = createDebug;
|
|
327
|
+
createDebug.coerce = coerce;
|
|
328
|
+
createDebug.disable = disable;
|
|
329
|
+
createDebug.enable = enable;
|
|
330
|
+
createDebug.enabled = enabled;
|
|
331
|
+
createDebug.humanize = env.humanize;
|
|
332
|
+
createDebug.destroy = destroy;
|
|
333
|
+
Object.keys(env).forEach((key) => {
|
|
334
|
+
createDebug[key] = env[key];
|
|
335
|
+
});
|
|
336
|
+
createDebug.names = [];
|
|
337
|
+
createDebug.skips = [];
|
|
338
|
+
createDebug.formatters = {};
|
|
339
|
+
function selectColor(namespace) {
|
|
340
|
+
let hash = 0;
|
|
341
|
+
for (let i = 0; i < namespace.length; i++) {
|
|
342
|
+
hash = (hash << 5) - hash + namespace.charCodeAt(i);
|
|
343
|
+
hash |= 0;
|
|
344
|
+
}
|
|
345
|
+
return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
|
|
346
|
+
}
|
|
347
|
+
createDebug.selectColor = selectColor;
|
|
348
|
+
function createDebug(namespace) {
|
|
349
|
+
let prevTime;
|
|
350
|
+
let enableOverride = null;
|
|
351
|
+
let namespacesCache;
|
|
352
|
+
let enabledCache;
|
|
353
|
+
function debug(...args) {
|
|
354
|
+
if (!debug.enabled) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const self = debug;
|
|
358
|
+
const curr = Number(/* @__PURE__ */ new Date());
|
|
359
|
+
const ms = curr - (prevTime || curr);
|
|
360
|
+
self.diff = ms;
|
|
361
|
+
self.prev = prevTime;
|
|
362
|
+
self.curr = curr;
|
|
363
|
+
prevTime = curr;
|
|
364
|
+
args[0] = createDebug.coerce(args[0]);
|
|
365
|
+
if (typeof args[0] !== "string") {
|
|
366
|
+
args.unshift("%O");
|
|
367
|
+
}
|
|
368
|
+
let index = 0;
|
|
369
|
+
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
|
|
370
|
+
if (match === "%%") {
|
|
371
|
+
return "%";
|
|
372
|
+
}
|
|
373
|
+
index++;
|
|
374
|
+
const formatter = createDebug.formatters[format];
|
|
375
|
+
if (typeof formatter === "function") {
|
|
376
|
+
const val = args[index];
|
|
377
|
+
match = formatter.call(self, val);
|
|
378
|
+
args.splice(index, 1);
|
|
379
|
+
index--;
|
|
380
|
+
}
|
|
381
|
+
return match;
|
|
382
|
+
});
|
|
383
|
+
createDebug.formatArgs.call(self, args);
|
|
384
|
+
const logFn = self.log || createDebug.log;
|
|
385
|
+
logFn.apply(self, args);
|
|
386
|
+
}
|
|
387
|
+
debug.namespace = namespace;
|
|
388
|
+
debug.useColors = createDebug.useColors();
|
|
389
|
+
debug.color = createDebug.selectColor(namespace);
|
|
390
|
+
debug.extend = extend;
|
|
391
|
+
debug.destroy = createDebug.destroy;
|
|
392
|
+
Object.defineProperty(debug, "enabled", {
|
|
393
|
+
enumerable: true,
|
|
394
|
+
configurable: false,
|
|
395
|
+
get: () => {
|
|
396
|
+
if (enableOverride !== null) {
|
|
397
|
+
return enableOverride;
|
|
398
|
+
}
|
|
399
|
+
if (namespacesCache !== createDebug.namespaces) {
|
|
400
|
+
namespacesCache = createDebug.namespaces;
|
|
401
|
+
enabledCache = createDebug.enabled(namespace);
|
|
402
|
+
}
|
|
403
|
+
return enabledCache;
|
|
404
|
+
},
|
|
405
|
+
set: (v) => {
|
|
406
|
+
enableOverride = v;
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
if (typeof createDebug.init === "function") {
|
|
410
|
+
createDebug.init(debug);
|
|
411
|
+
}
|
|
412
|
+
return debug;
|
|
413
|
+
}
|
|
414
|
+
function extend(namespace, delimiter) {
|
|
415
|
+
const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace);
|
|
416
|
+
newDebug.log = this.log;
|
|
417
|
+
return newDebug;
|
|
418
|
+
}
|
|
419
|
+
function enable(namespaces) {
|
|
420
|
+
createDebug.save(namespaces);
|
|
421
|
+
createDebug.namespaces = namespaces;
|
|
422
|
+
createDebug.names = [];
|
|
423
|
+
createDebug.skips = [];
|
|
424
|
+
const split = (typeof namespaces === "string" ? namespaces : "").trim().replace(/\s+/g, ",").split(",").filter(Boolean);
|
|
425
|
+
for (const ns of split) {
|
|
426
|
+
if (ns[0] === "-") {
|
|
427
|
+
createDebug.skips.push(ns.slice(1));
|
|
428
|
+
} else {
|
|
429
|
+
createDebug.names.push(ns);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
function matchesTemplate(search, template) {
|
|
434
|
+
let searchIndex = 0;
|
|
435
|
+
let templateIndex = 0;
|
|
436
|
+
let starIndex = -1;
|
|
437
|
+
let matchIndex = 0;
|
|
438
|
+
while (searchIndex < search.length) {
|
|
439
|
+
if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === "*")) {
|
|
440
|
+
if (template[templateIndex] === "*") {
|
|
441
|
+
starIndex = templateIndex;
|
|
442
|
+
matchIndex = searchIndex;
|
|
443
|
+
templateIndex++;
|
|
444
|
+
} else {
|
|
445
|
+
searchIndex++;
|
|
446
|
+
templateIndex++;
|
|
447
|
+
}
|
|
448
|
+
} else if (starIndex !== -1) {
|
|
449
|
+
templateIndex = starIndex + 1;
|
|
450
|
+
matchIndex++;
|
|
451
|
+
searchIndex = matchIndex;
|
|
452
|
+
} else {
|
|
453
|
+
return false;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
while (templateIndex < template.length && template[templateIndex] === "*") {
|
|
457
|
+
templateIndex++;
|
|
458
|
+
}
|
|
459
|
+
return templateIndex === template.length;
|
|
460
|
+
}
|
|
461
|
+
function disable() {
|
|
462
|
+
const namespaces = [...createDebug.names, ...createDebug.skips.map((namespace) => "-" + namespace)].join(",");
|
|
463
|
+
createDebug.enable("");
|
|
464
|
+
return namespaces;
|
|
465
|
+
}
|
|
466
|
+
function enabled(name) {
|
|
467
|
+
for (const skip of createDebug.skips) {
|
|
468
|
+
if (matchesTemplate(name, skip)) {
|
|
469
|
+
return false;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
for (const ns of createDebug.names) {
|
|
473
|
+
if (matchesTemplate(name, ns)) {
|
|
474
|
+
return true;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return false;
|
|
478
|
+
}
|
|
479
|
+
function coerce(val) {
|
|
480
|
+
if (val instanceof Error) {
|
|
481
|
+
return val.stack || val.message;
|
|
482
|
+
}
|
|
483
|
+
return val;
|
|
484
|
+
}
|
|
485
|
+
function destroy() {
|
|
486
|
+
console.warn(
|
|
487
|
+
"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
createDebug.enable(createDebug.load());
|
|
491
|
+
return createDebug;
|
|
492
|
+
}
|
|
493
|
+
var common_default = setup;
|
|
494
|
+
|
|
495
|
+
// ../../shared/nodejs/src/log/logger.ts
|
|
496
|
+
var BASIC_COLORS = [6, 2, 3, 4, 5, 1];
|
|
497
|
+
var EXTENDED_COLORS = [
|
|
498
|
+
20,
|
|
499
|
+
21,
|
|
500
|
+
26,
|
|
501
|
+
27,
|
|
502
|
+
32,
|
|
503
|
+
33,
|
|
504
|
+
38,
|
|
505
|
+
39,
|
|
506
|
+
40,
|
|
507
|
+
41,
|
|
508
|
+
42,
|
|
509
|
+
43,
|
|
510
|
+
44,
|
|
511
|
+
45,
|
|
512
|
+
56,
|
|
513
|
+
57,
|
|
514
|
+
62,
|
|
515
|
+
63,
|
|
516
|
+
68,
|
|
517
|
+
69,
|
|
518
|
+
74,
|
|
519
|
+
75,
|
|
520
|
+
76,
|
|
521
|
+
77,
|
|
522
|
+
78,
|
|
523
|
+
79,
|
|
524
|
+
80,
|
|
525
|
+
81,
|
|
526
|
+
92,
|
|
527
|
+
93,
|
|
528
|
+
98,
|
|
529
|
+
99,
|
|
530
|
+
112,
|
|
531
|
+
113,
|
|
532
|
+
128,
|
|
533
|
+
129,
|
|
534
|
+
134,
|
|
535
|
+
135,
|
|
536
|
+
148,
|
|
537
|
+
149,
|
|
538
|
+
160,
|
|
539
|
+
161,
|
|
540
|
+
162,
|
|
541
|
+
163,
|
|
542
|
+
164,
|
|
543
|
+
165,
|
|
544
|
+
166,
|
|
545
|
+
167,
|
|
546
|
+
168,
|
|
547
|
+
169,
|
|
548
|
+
170,
|
|
549
|
+
171,
|
|
550
|
+
172,
|
|
551
|
+
173,
|
|
552
|
+
178,
|
|
553
|
+
179,
|
|
554
|
+
184,
|
|
555
|
+
185,
|
|
556
|
+
196,
|
|
557
|
+
197,
|
|
558
|
+
198,
|
|
559
|
+
199,
|
|
560
|
+
200,
|
|
561
|
+
201,
|
|
562
|
+
202,
|
|
563
|
+
203,
|
|
564
|
+
204,
|
|
565
|
+
205,
|
|
566
|
+
206,
|
|
567
|
+
207,
|
|
568
|
+
208,
|
|
569
|
+
209,
|
|
570
|
+
214,
|
|
571
|
+
215,
|
|
572
|
+
220,
|
|
573
|
+
221
|
|
574
|
+
];
|
|
575
|
+
function supportsExtendedColors() {
|
|
576
|
+
try {
|
|
577
|
+
const supportsColor = require_supports_color();
|
|
578
|
+
return supportsColor && (supportsColor.stderr || supportsColor).level >= 2;
|
|
579
|
+
} catch {
|
|
580
|
+
return false;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
function shouldUseColors() {
|
|
584
|
+
return false;
|
|
585
|
+
}
|
|
586
|
+
function formatArgs(args) {
|
|
587
|
+
const { namespace, useColors, color } = this;
|
|
588
|
+
if (useColors) {
|
|
589
|
+
const colorCode = color < 8 ? `3${color}` : `38;5;${color}`;
|
|
590
|
+
const prefix = `\x1B[${colorCode};1m${namespace}\x1B[0m`;
|
|
591
|
+
args[0] = `${prefix} ${args[0]}`.split("\n").join(`
|
|
592
|
+
${prefix} `);
|
|
593
|
+
args.push(`\x1B[${colorCode}m+${humanizeTime(this.diff)}\x1B[0m`);
|
|
594
|
+
} else {
|
|
595
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
596
|
+
args[0] = `${timestamp} ${namespace} ${args[0]}`;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
function writeOutput(...args) {
|
|
600
|
+
process.stderr.write(import_util.default.format(...args) + "\n");
|
|
601
|
+
}
|
|
602
|
+
function saveConfig(namespaces) {
|
|
603
|
+
if (namespaces) {
|
|
604
|
+
process.env.DEBUG = namespaces;
|
|
605
|
+
} else {
|
|
606
|
+
delete process.env.DEBUG;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
function loadConfig() {
|
|
610
|
+
return process.env.DEBUG;
|
|
611
|
+
}
|
|
612
|
+
function humanizeTime(milliseconds) {
|
|
613
|
+
if (milliseconds >= 1e3) {
|
|
614
|
+
const seconds = Math.round(milliseconds / 1e3);
|
|
615
|
+
return `${seconds}s`;
|
|
616
|
+
}
|
|
617
|
+
return `${milliseconds}ms`;
|
|
618
|
+
}
|
|
619
|
+
function createLoggerConfig() {
|
|
620
|
+
const colors = supportsExtendedColors() ? EXTENDED_COLORS : BASIC_COLORS;
|
|
621
|
+
return {
|
|
622
|
+
colors,
|
|
623
|
+
useColors: shouldUseColors,
|
|
624
|
+
formatArgs,
|
|
625
|
+
log: writeOutput,
|
|
626
|
+
save: saveConfig,
|
|
627
|
+
load: loadConfig,
|
|
628
|
+
humanize: humanizeTime
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
var config = createLoggerConfig();
|
|
632
|
+
var logger = common_default(config);
|
|
633
|
+
if (logger.formatters) {
|
|
634
|
+
logger.formatters.o = function(value) {
|
|
635
|
+
return import_util.default.inspect(value, { colors: this.useColors, compact: true }).split("\n").map((line) => line.trim()).join(" ");
|
|
636
|
+
};
|
|
637
|
+
logger.formatters.O = function(value) {
|
|
638
|
+
return import_util.default.inspect(value, { colors: this.useColors, compact: false });
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
var logger_default = logger;
|
|
642
|
+
|
|
643
|
+
// ../../shared/nodejs/src/log/index.ts
|
|
644
|
+
var log_default = logger_default;
|
|
645
|
+
|
|
646
|
+
// ../../shared/nodejs/src/logger.ts
|
|
647
|
+
var getFileLocation = () => {
|
|
648
|
+
let errorObject = new Error();
|
|
649
|
+
if (errorObject.stack === void 0) {
|
|
650
|
+
return "N/A";
|
|
651
|
+
}
|
|
652
|
+
let errorStack = errorObject.stack.split("\n");
|
|
653
|
+
for (let i = 1; i < errorStack.length; i++) {
|
|
654
|
+
if (!errorStack[i]?.includes("logger.js")) {
|
|
655
|
+
return errorStack[i]?.match(/(?<=\().+?(?=\))/g);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
return "N/A";
|
|
659
|
+
};
|
|
660
|
+
var buildLogger = (pluginId, version, { fileLocation = true } = {}) => {
|
|
661
|
+
const namespace = `com.supertokens.plugin.${pluginId}`;
|
|
662
|
+
function logDebugMessage2(message) {
|
|
663
|
+
if (log_default.enabled(namespace)) {
|
|
664
|
+
log_default(namespace)(
|
|
665
|
+
`{t: "${(/* @__PURE__ */ new Date()).toISOString()}", message: "${message}", file: "${fileLocation ? getFileLocation() : "N/A"}" version: "${version}"}`
|
|
666
|
+
);
|
|
667
|
+
console.log();
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
function enableDebugLogs2() {
|
|
671
|
+
log_default.enable(namespace);
|
|
672
|
+
}
|
|
673
|
+
return {
|
|
674
|
+
logDebugMessage: logDebugMessage2,
|
|
675
|
+
enableDebugLogs: enableDebugLogs2
|
|
676
|
+
};
|
|
677
|
+
};
|
|
678
|
+
|
|
679
|
+
// src/plugin.ts
|
|
680
|
+
var import_node = require("@rownd/node");
|
|
681
|
+
var import_supertokens_node2 = __toESM(require("supertokens-node"));
|
|
682
|
+
|
|
683
|
+
// src/constants.ts
|
|
684
|
+
var PLUGIN_ID = "supertokens-plugin-rownd";
|
|
685
|
+
var PLUGIN_SDK_VERSION = ["23.0.0", "23.0.1", ">=23.0.1"];
|
|
686
|
+
var HANDLE_BASE_PATH = "/plugin/rownd";
|
|
687
|
+
var PUBLIC_TENANT_ID = "public";
|
|
688
|
+
var GUEST_AUTH_METHOD_ID = "guest";
|
|
689
|
+
var ANONYMOUS_AUTH_METHOD_ID = "anonymous";
|
|
690
|
+
var ROWND_JWT_CLAIMS = {
|
|
691
|
+
AppUserId: "https://auth.rownd.io/app_user_id",
|
|
692
|
+
IsVerifiedUser: "https://auth.rownd.io/is_verified_user",
|
|
693
|
+
IsAnonymous: "https://auth.rownd.io/is_anonymous",
|
|
694
|
+
IssuedOffline: "https://auth.rownd.io/issued_offline",
|
|
695
|
+
JwtType: "https://auth.rownd.io/jwt_type",
|
|
696
|
+
PlatformJwt: "https://auth.rownd.io/platform_jwt",
|
|
697
|
+
AuthLevel: "https://auth.rownd.io/auth_level"
|
|
698
|
+
};
|
|
699
|
+
var DEFAULT_ROWND_SCHEMA = {
|
|
700
|
+
zip_code: {
|
|
701
|
+
display_name: "Zip code",
|
|
702
|
+
type: "string",
|
|
703
|
+
user_visible: true
|
|
704
|
+
},
|
|
705
|
+
last_name: {
|
|
706
|
+
display_name: "Last name",
|
|
707
|
+
type: "string",
|
|
708
|
+
user_visible: true
|
|
709
|
+
},
|
|
710
|
+
nick_name: {
|
|
711
|
+
display_name: "Nick name",
|
|
712
|
+
type: "string",
|
|
713
|
+
user_visible: true
|
|
714
|
+
},
|
|
715
|
+
first_name: {
|
|
716
|
+
display_name: "First name",
|
|
717
|
+
type: "string",
|
|
718
|
+
user_visible: true
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
// src/logger.ts
|
|
723
|
+
var { logDebugMessage, enableDebugLogs } = buildLogger(
|
|
724
|
+
PLUGIN_ID,
|
|
725
|
+
PLUGIN_SDK_VERSION
|
|
726
|
+
);
|
|
727
|
+
|
|
728
|
+
// src/telemetry/axiomTelemetryClient.ts
|
|
729
|
+
var DEFAULT_AXIOM_URL = "https://api.axiom.co/v1/datasets";
|
|
730
|
+
var AxiomTelemetryClient = class {
|
|
731
|
+
constructor(token, dataset, endpoint) {
|
|
732
|
+
this.token = token;
|
|
733
|
+
this.dataset = dataset;
|
|
734
|
+
const baseUrl = (endpoint ?? DEFAULT_AXIOM_URL).replace(/\/$/, "");
|
|
735
|
+
this.url = `${baseUrl}/${dataset}/ingest`;
|
|
736
|
+
}
|
|
737
|
+
token;
|
|
738
|
+
dataset;
|
|
739
|
+
url;
|
|
740
|
+
async recordEvent(event) {
|
|
741
|
+
await fetch(this.url, {
|
|
742
|
+
method: "POST",
|
|
743
|
+
headers: {
|
|
744
|
+
Authorization: `Bearer ${this.token}`,
|
|
745
|
+
"Content-Type": "application/json"
|
|
746
|
+
},
|
|
747
|
+
body: JSON.stringify([
|
|
748
|
+
{
|
|
749
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
750
|
+
plugin: PLUGIN_ID,
|
|
751
|
+
...event
|
|
752
|
+
}
|
|
753
|
+
])
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
|
|
758
|
+
// src/telemetry/openTelemetryClient.ts
|
|
759
|
+
var import_api = require("@opentelemetry/api");
|
|
760
|
+
var OpenTelemetryClient = class {
|
|
761
|
+
recordEvent(event) {
|
|
762
|
+
const tracer = import_api.trace.getTracer("supertokens-plugin-rownd", "0.1.0");
|
|
763
|
+
const span = tracer.startSpan("rownd.migrate");
|
|
764
|
+
span.setAttributes({
|
|
765
|
+
"rownd.outcome": event.outcome,
|
|
766
|
+
"rownd.duration_ms": event.durationMs,
|
|
767
|
+
"rownd.tenant_id": event.tenantId ?? "",
|
|
768
|
+
"rownd.rownd_user_id": event.rowndUserId ?? "",
|
|
769
|
+
"rownd.supertokens_user_id": event.superTokensUserId ?? ""
|
|
770
|
+
});
|
|
771
|
+
if (event.outcome === "error") {
|
|
772
|
+
const err = new Error(event.error.message);
|
|
773
|
+
if (event.error.name) {
|
|
774
|
+
err.name = event.error.name;
|
|
775
|
+
}
|
|
776
|
+
span.recordException(err);
|
|
777
|
+
span.setStatus({
|
|
778
|
+
code: import_api.SpanStatusCode.ERROR,
|
|
779
|
+
message: event.error.message
|
|
780
|
+
});
|
|
781
|
+
} else {
|
|
782
|
+
span.setStatus({ code: import_api.SpanStatusCode.OK });
|
|
783
|
+
}
|
|
784
|
+
span.end();
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
|
|
788
|
+
// src/telemetry/createTelemetryClient.ts
|
|
789
|
+
function createClient(telemetryConfig) {
|
|
790
|
+
let client;
|
|
791
|
+
if (telemetryConfig?.provider === "opentelemetry") {
|
|
792
|
+
client = new OpenTelemetryClient();
|
|
793
|
+
} else if (telemetryConfig?.provider === "axiom") {
|
|
794
|
+
client = new AxiomTelemetryClient(
|
|
795
|
+
telemetryConfig.token,
|
|
796
|
+
telemetryConfig.dataset,
|
|
797
|
+
telemetryConfig.url
|
|
798
|
+
);
|
|
799
|
+
} else if (telemetryConfig?.provider === "custom") {
|
|
800
|
+
client = telemetryConfig.factory();
|
|
801
|
+
}
|
|
802
|
+
return {
|
|
803
|
+
recordSuccess: (event) => {
|
|
804
|
+
if (!client) {
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
safeRecordEvent(client, event, "success");
|
|
808
|
+
},
|
|
809
|
+
recordError: (input) => {
|
|
810
|
+
if (!client) {
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
const event = {
|
|
814
|
+
outcome: "error",
|
|
815
|
+
durationMs: Date.now() - input.startedAt,
|
|
816
|
+
tenantId: input.tenantId,
|
|
817
|
+
rowndUserId: input.rowndUserId,
|
|
818
|
+
superTokensUserId: input.superTokensUserId,
|
|
819
|
+
error: {
|
|
820
|
+
message: input.error instanceof Error ? input.error.message : "Unknown error",
|
|
821
|
+
name: input.error instanceof Error ? input.error.name : void 0
|
|
822
|
+
}
|
|
823
|
+
};
|
|
824
|
+
safeRecordEvent(client, event, "error");
|
|
825
|
+
}
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
function safeRecordEvent(client, event, outcome) {
|
|
829
|
+
try {
|
|
830
|
+
Promise.resolve(client.recordEvent(event)).catch((error) => {
|
|
831
|
+
logDebugMessage(
|
|
832
|
+
`Failed to record telemetry ${outcome} event. Error: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
833
|
+
);
|
|
834
|
+
});
|
|
835
|
+
} catch (error) {
|
|
836
|
+
logDebugMessage(
|
|
837
|
+
`Failed to record telemetry ${outcome} event. Error: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
838
|
+
);
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// src/pluginImplementation.ts
|
|
843
|
+
var import_crypto = require("crypto");
|
|
844
|
+
var import_supertokens_node = __toESM(require("supertokens-node"));
|
|
845
|
+
var import_accountlinking = __toESM(require("supertokens-node/recipe/accountlinking"));
|
|
846
|
+
var import_emailverification = __toESM(require("supertokens-node/recipe/emailverification"));
|
|
847
|
+
var import_passwordless = __toESM(require("supertokens-node/recipe/passwordless"));
|
|
848
|
+
var import_session = __toESM(require("supertokens-node/recipe/session"));
|
|
849
|
+
var import_claims = require("supertokens-node/recipe/session/claims");
|
|
850
|
+
var import_thirdparty = __toESM(require("supertokens-node/recipe/thirdparty"));
|
|
851
|
+
var import_usermetadata2 = __toESM(require("supertokens-node/recipe/usermetadata"));
|
|
852
|
+
|
|
853
|
+
// src/errors.ts
|
|
854
|
+
var ROWND_PLUGIN_ERROR_MESSAGES = {
|
|
855
|
+
MISSING_AUTHORIZATION_HEADER: "Missing authorization header",
|
|
856
|
+
INVALID_TOKEN: "Invalid token",
|
|
857
|
+
ROWND_USER_NOT_FOUND: "User not found in Rownd"
|
|
858
|
+
};
|
|
859
|
+
var RowndPluginError = class extends Error {
|
|
860
|
+
constructor(type) {
|
|
861
|
+
super(ROWND_PLUGIN_ERROR_MESSAGES[type]);
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
|
|
865
|
+
// src/pluginImplementation.ts
|
|
866
|
+
function rewriteLinkPath(inputUrl, targetPath, searchParams) {
|
|
867
|
+
try {
|
|
868
|
+
const url = new URL(inputUrl);
|
|
869
|
+
url.pathname = `/${targetPath.replace(/^\//, "")}`;
|
|
870
|
+
for (const [key, value] of Object.entries(searchParams ?? {})) {
|
|
871
|
+
url.searchParams.set(key, value);
|
|
872
|
+
}
|
|
873
|
+
return url.toString();
|
|
874
|
+
} catch {
|
|
875
|
+
const [path = inputUrl, query = ""] = inputUrl.replace(/auth\/verify[^?]*/, targetPath).split("?");
|
|
876
|
+
const params = new URLSearchParams(query);
|
|
877
|
+
for (const [key, value] of Object.entries(searchParams ?? {})) {
|
|
878
|
+
params.set(key, value);
|
|
879
|
+
}
|
|
880
|
+
const queryString = params.toString();
|
|
881
|
+
return queryString ? `${path}?${queryString}` : path;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
var rowndClient;
|
|
885
|
+
var pluginConfig;
|
|
886
|
+
function setRowndClient(client) {
|
|
887
|
+
rowndClient = client;
|
|
888
|
+
}
|
|
889
|
+
function getRowndClient() {
|
|
890
|
+
if (!rowndClient) {
|
|
891
|
+
throw new Error("Rownd client not initialized");
|
|
892
|
+
}
|
|
893
|
+
return rowndClient;
|
|
894
|
+
}
|
|
895
|
+
function setPluginConfig(config2) {
|
|
896
|
+
pluginConfig = config2;
|
|
897
|
+
}
|
|
898
|
+
async function parseRequest(req) {
|
|
899
|
+
const authHeader = req.getHeaderValue("authorization");
|
|
900
|
+
if (!authHeader) {
|
|
901
|
+
throw new RowndPluginError("MISSING_AUTHORIZATION_HEADER");
|
|
902
|
+
}
|
|
903
|
+
const token = authHeader.replace(/^Bearer /i, "");
|
|
904
|
+
if (!token) {
|
|
905
|
+
throw new RowndPluginError("INVALID_TOKEN");
|
|
906
|
+
}
|
|
907
|
+
return {
|
|
908
|
+
token
|
|
909
|
+
};
|
|
910
|
+
}
|
|
911
|
+
function handleGetAppConfig(deps) {
|
|
912
|
+
return async (req) => {
|
|
913
|
+
const appVariantId = getRequestedAppVariantIdFromRequest(req);
|
|
914
|
+
const appConfig = buildAppConfig(
|
|
915
|
+
deps.pluginConfig,
|
|
916
|
+
deps.stConfig,
|
|
917
|
+
appVariantId
|
|
918
|
+
);
|
|
919
|
+
if (!appConfig) {
|
|
920
|
+
return {
|
|
921
|
+
status: "ERROR",
|
|
922
|
+
message: `Unknown Rownd app variant: ${appVariantId}`
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
return {
|
|
926
|
+
status: "OK",
|
|
927
|
+
...appConfig
|
|
928
|
+
};
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
function handleGuestLogin(deps) {
|
|
932
|
+
return async (req, res, _session, userContext) => {
|
|
933
|
+
const startedAt = Date.now();
|
|
934
|
+
const guestId = `guest_${(0, import_crypto.randomUUID)()}`;
|
|
935
|
+
try {
|
|
936
|
+
const body = parseGuestBody(await getJsonBody(req));
|
|
937
|
+
const appVariantId = getRequestedAppVariantIdFromRequest(req);
|
|
938
|
+
assertRowndAppVariantIsConfigured(appVariantId);
|
|
939
|
+
const thirdPartyId = body.authLevel === ANONYMOUS_AUTH_METHOD_ID ? ANONYMOUS_AUTH_METHOD_ID : GUEST_AUTH_METHOD_ID;
|
|
940
|
+
const thirdPartyUserId = thirdPartyId === ANONYMOUS_AUTH_METHOD_ID ? `anon_${(0, import_crypto.randomUUID)()}` : guestId;
|
|
941
|
+
const response = await import_thirdparty.default.manuallyCreateOrUpdateUser(
|
|
942
|
+
PUBLIC_TENANT_ID,
|
|
943
|
+
thirdPartyId,
|
|
944
|
+
thirdPartyUserId,
|
|
945
|
+
`${thirdPartyUserId}@anonymous.local`,
|
|
946
|
+
false,
|
|
947
|
+
void 0,
|
|
948
|
+
userContext
|
|
949
|
+
);
|
|
950
|
+
if (response.status !== "OK") {
|
|
951
|
+
throw new Error(
|
|
952
|
+
`Guest user creation failed with status: ${response.status}`
|
|
953
|
+
);
|
|
954
|
+
}
|
|
955
|
+
await import_session.default.createNewSession(
|
|
956
|
+
req,
|
|
957
|
+
res,
|
|
958
|
+
PUBLIC_TENANT_ID,
|
|
959
|
+
response.recipeUserId,
|
|
960
|
+
{
|
|
961
|
+
...buildRowndAudience({}, appVariantId),
|
|
962
|
+
auth_level: GUEST_AUTH_METHOD_ID,
|
|
963
|
+
is_anonymous: true,
|
|
964
|
+
app_user_id: response.user.id
|
|
965
|
+
},
|
|
966
|
+
{},
|
|
967
|
+
userContext
|
|
968
|
+
);
|
|
969
|
+
logDebugMessage(`Guest session created for user: ${response.user.id}`);
|
|
970
|
+
deps.telemetryClient.recordSuccess({
|
|
971
|
+
outcome: "success",
|
|
972
|
+
durationMs: Date.now() - startedAt,
|
|
973
|
+
tenantId: PUBLIC_TENANT_ID,
|
|
974
|
+
superTokensUserId: response.user.id
|
|
975
|
+
});
|
|
976
|
+
return {
|
|
977
|
+
status: "OK",
|
|
978
|
+
createdNewRecipeUser: response.createdNewRecipeUser
|
|
979
|
+
};
|
|
980
|
+
} catch (error) {
|
|
981
|
+
logDebugMessage(`Guest login failed. Error: ${getErrorMessage(error)}`);
|
|
982
|
+
deps.telemetryClient.recordError({
|
|
983
|
+
error,
|
|
984
|
+
startedAt,
|
|
985
|
+
tenantId: PUBLIC_TENANT_ID
|
|
986
|
+
});
|
|
987
|
+
return {
|
|
988
|
+
status: "ERROR",
|
|
989
|
+
message: "Guest login failed"
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
};
|
|
993
|
+
}
|
|
994
|
+
function handleMigrate(deps) {
|
|
995
|
+
return async (req, res, _session, userContext) => {
|
|
996
|
+
const startedAt = Date.now();
|
|
997
|
+
let tenantId = PUBLIC_TENANT_ID;
|
|
998
|
+
let rowndUserId;
|
|
999
|
+
let superTokensUserId;
|
|
1000
|
+
let user;
|
|
1001
|
+
let recipeUserId;
|
|
1002
|
+
try {
|
|
1003
|
+
if (!deps.stConfig.supertokens) {
|
|
1004
|
+
throw new Error("Supertokens config not found");
|
|
1005
|
+
}
|
|
1006
|
+
const parsed = await parseRequest(req);
|
|
1007
|
+
const appVariantId = getRequestedAppVariantIdFromRequest(req);
|
|
1008
|
+
assertRowndAppVariantIsConfigured(appVariantId);
|
|
1009
|
+
rowndUserId = await validateRowndToken(parsed.token);
|
|
1010
|
+
user = await import_supertokens_node.default.getUser(rowndUserId, userContext);
|
|
1011
|
+
if (!user) {
|
|
1012
|
+
const rowndUser = await fetchRowndUserInfo(rowndUserId);
|
|
1013
|
+
const stUserImport = mapRowndUserToSuperTokens(rowndUser);
|
|
1014
|
+
try {
|
|
1015
|
+
const importedUser = await importUser(
|
|
1016
|
+
stUserImport,
|
|
1017
|
+
deps.stConfig.supertokens
|
|
1018
|
+
);
|
|
1019
|
+
superTokensUserId = importedUser.id;
|
|
1020
|
+
if (importedUser.loginMethods[0]?.recipeUserId) {
|
|
1021
|
+
recipeUserId = import_supertokens_node.default.convertToRecipeUserId(
|
|
1022
|
+
importedUser.loginMethods[0].recipeUserId
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
1025
|
+
} catch (err) {
|
|
1026
|
+
user = await import_supertokens_node.default.getUser(rowndUserId, userContext);
|
|
1027
|
+
if (!user) {
|
|
1028
|
+
throw err;
|
|
1029
|
+
}
|
|
1030
|
+
superTokensUserId = user.id;
|
|
1031
|
+
recipeUserId = user.loginMethods[0]?.recipeUserId;
|
|
1032
|
+
logDebugMessage(
|
|
1033
|
+
`User already migrated (race condition). tenantId: ${PUBLIC_TENANT_ID}, rowndUserId: ${rowndUserId}`
|
|
1034
|
+
);
|
|
1035
|
+
}
|
|
1036
|
+
logDebugMessage(
|
|
1037
|
+
`User migrated successfully. tenantId: ${PUBLIC_TENANT_ID}, rowndUserId: ${rowndUserId}`
|
|
1038
|
+
);
|
|
1039
|
+
} else {
|
|
1040
|
+
superTokensUserId = user.id;
|
|
1041
|
+
recipeUserId = user.loginMethods[0]?.recipeUserId;
|
|
1042
|
+
logDebugMessage(
|
|
1043
|
+
`User already migrated. tenantId: ${PUBLIC_TENANT_ID}, rowndUserId: ${rowndUserId}`
|
|
1044
|
+
);
|
|
1045
|
+
}
|
|
1046
|
+
if (superTokensUserId) {
|
|
1047
|
+
await recordRowndAppVariantForUser(superTokensUserId, appVariantId);
|
|
1048
|
+
}
|
|
1049
|
+
if (!recipeUserId) {
|
|
1050
|
+
throw new Error("User not found or has no login methods");
|
|
1051
|
+
}
|
|
1052
|
+
await import_session.default.createNewSession(
|
|
1053
|
+
req,
|
|
1054
|
+
res,
|
|
1055
|
+
PUBLIC_TENANT_ID,
|
|
1056
|
+
recipeUserId,
|
|
1057
|
+
{
|
|
1058
|
+
...buildRowndAudience({}, appVariantId)
|
|
1059
|
+
},
|
|
1060
|
+
{},
|
|
1061
|
+
userContext
|
|
1062
|
+
);
|
|
1063
|
+
logDebugMessage(
|
|
1064
|
+
`Session migrated successfully. tenantId: ${PUBLIC_TENANT_ID}, userId: ${superTokensUserId}`
|
|
1065
|
+
);
|
|
1066
|
+
deps.telemetryClient.recordSuccess({
|
|
1067
|
+
outcome: "success",
|
|
1068
|
+
durationMs: Date.now() - startedAt,
|
|
1069
|
+
tenantId,
|
|
1070
|
+
rowndUserId,
|
|
1071
|
+
superTokensUserId
|
|
1072
|
+
});
|
|
1073
|
+
return { status: "OK" };
|
|
1074
|
+
} catch (error) {
|
|
1075
|
+
logDebugMessage(`Migration failed. Error: ${getErrorMessage(error)}`);
|
|
1076
|
+
deps.telemetryClient.recordError({
|
|
1077
|
+
error,
|
|
1078
|
+
startedAt,
|
|
1079
|
+
tenantId,
|
|
1080
|
+
rowndUserId,
|
|
1081
|
+
superTokensUserId
|
|
1082
|
+
});
|
|
1083
|
+
return {
|
|
1084
|
+
status: "ERROR",
|
|
1085
|
+
message: error instanceof RowndPluginError ? error.message : "Migration failed"
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
function handleGetUser() {
|
|
1091
|
+
return async (_req, _res, maybeSession) => {
|
|
1092
|
+
const session = requireSession(maybeSession);
|
|
1093
|
+
return {
|
|
1094
|
+
status: "OK",
|
|
1095
|
+
...await getUserById(session.getUserId())
|
|
1096
|
+
};
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
function handleUpdateUser() {
|
|
1100
|
+
return async (req, _res, maybeSession, userContext) => {
|
|
1101
|
+
const session = requireSession(maybeSession);
|
|
1102
|
+
const appVariantId = getRequestedAppVariantIdFromRequest(req);
|
|
1103
|
+
assertRowndAppVariantIsConfigured(appVariantId);
|
|
1104
|
+
const payload = parseUpdateUserBody(await getJsonBody(req));
|
|
1105
|
+
const inputData = payload.data ?? {};
|
|
1106
|
+
const requestUserContext = {
|
|
1107
|
+
...userContext,
|
|
1108
|
+
...payload.context
|
|
1109
|
+
};
|
|
1110
|
+
const { email, ...dataWithoutEmail } = inputData;
|
|
1111
|
+
const hasEmailUpdate = hasOwn(inputData, "email") && typeof email === "string";
|
|
1112
|
+
const permissionError = validateWritableFields(
|
|
1113
|
+
Object.keys(dataWithoutEmail)
|
|
1114
|
+
);
|
|
1115
|
+
if (permissionError) {
|
|
1116
|
+
return permissionError;
|
|
1117
|
+
}
|
|
1118
|
+
if (Object.keys(dataWithoutEmail).length > 0) {
|
|
1119
|
+
await updateUserData(session.getUserId(), dataWithoutEmail);
|
|
1120
|
+
}
|
|
1121
|
+
if (hasEmailUpdate) {
|
|
1122
|
+
return {
|
|
1123
|
+
status: "OK",
|
|
1124
|
+
...await startPendingEmailVerification({
|
|
1125
|
+
userId: session.getUserId(),
|
|
1126
|
+
recipeUserId: session.getRecipeUserId(),
|
|
1127
|
+
tenantId: session.getTenantId(),
|
|
1128
|
+
email,
|
|
1129
|
+
pendingVerificationId: (0, import_crypto.randomUUID)(),
|
|
1130
|
+
userContext: appVariantId ? { ...requestUserContext, rowndAppVariantId: appVariantId } : requestUserContext
|
|
1131
|
+
})
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
return {
|
|
1135
|
+
status: "OK",
|
|
1136
|
+
...await getUserById(session.getUserId())
|
|
1137
|
+
};
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
function handleDeleteUser() {
|
|
1141
|
+
return async (_req, _res, maybeSession) => {
|
|
1142
|
+
const session = requireSession(maybeSession);
|
|
1143
|
+
await import_supertokens_node.default.deleteUser(session.getUserId(), true);
|
|
1144
|
+
return { status: "OK" };
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
1147
|
+
function handleSignOut() {
|
|
1148
|
+
return async (_req, _res, maybeSession, userContext) => {
|
|
1149
|
+
const session = requireSession(maybeSession);
|
|
1150
|
+
await import_session.default.revokeAllSessionsForUser(
|
|
1151
|
+
session.getUserId(),
|
|
1152
|
+
true,
|
|
1153
|
+
session.getTenantId(),
|
|
1154
|
+
userContext
|
|
1155
|
+
);
|
|
1156
|
+
return { status: "OK" };
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
function handleGetUserMeta() {
|
|
1160
|
+
return async (_req, _res, maybeSession) => {
|
|
1161
|
+
const session = requireSession(maybeSession);
|
|
1162
|
+
const metadata = await getUserMetadata(session.getUserId());
|
|
1163
|
+
return {
|
|
1164
|
+
status: "OK",
|
|
1165
|
+
id: session.getUserId(),
|
|
1166
|
+
meta: Object.fromEntries(
|
|
1167
|
+
Object.entries(metadata).filter(
|
|
1168
|
+
([key]) => !isInternalMetadataField(key)
|
|
1169
|
+
)
|
|
1170
|
+
)
|
|
1171
|
+
};
|
|
1172
|
+
};
|
|
1173
|
+
}
|
|
1174
|
+
function handleUpdateUserMeta() {
|
|
1175
|
+
return async (req, _res, maybeSession) => {
|
|
1176
|
+
const session = requireSession(maybeSession);
|
|
1177
|
+
const payload = parseUpdateMetaBody(await getJsonBody(req));
|
|
1178
|
+
const internalField = Object.keys(payload.meta ?? {}).find(
|
|
1179
|
+
isInternalMetadataField
|
|
1180
|
+
);
|
|
1181
|
+
if (internalField) {
|
|
1182
|
+
return {
|
|
1183
|
+
status: "ERROR",
|
|
1184
|
+
code: 403,
|
|
1185
|
+
message: `field is not writable: ${internalField}`
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1188
|
+
return {
|
|
1189
|
+
status: "OK",
|
|
1190
|
+
...await updateUserMetadata(session.getUserId(), payload.meta ?? {})
|
|
1191
|
+
};
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
function handleGetUserField() {
|
|
1195
|
+
return async (req, _res, maybeSession) => {
|
|
1196
|
+
const session = requireSession(maybeSession);
|
|
1197
|
+
const field = req.getKeyValueFromQuery("field");
|
|
1198
|
+
if (!field) {
|
|
1199
|
+
return missingFieldResponse();
|
|
1200
|
+
}
|
|
1201
|
+
const user = await getUserById(session.getUserId());
|
|
1202
|
+
return {
|
|
1203
|
+
status: "OK",
|
|
1204
|
+
value: user.data[field]
|
|
1205
|
+
};
|
|
1206
|
+
};
|
|
1207
|
+
}
|
|
1208
|
+
function handleUpdateUserField() {
|
|
1209
|
+
return async (req, _res, maybeSession, userContext) => {
|
|
1210
|
+
const session = requireSession(maybeSession);
|
|
1211
|
+
const appVariantId = getRequestedAppVariantIdFromRequest(req);
|
|
1212
|
+
assertRowndAppVariantIsConfigured(appVariantId);
|
|
1213
|
+
const field = req.getKeyValueFromQuery("field");
|
|
1214
|
+
if (!field) {
|
|
1215
|
+
return missingFieldResponse();
|
|
1216
|
+
}
|
|
1217
|
+
const payload = parseUpdateFieldBody(await getJsonBody(req));
|
|
1218
|
+
if (field === "email" && typeof payload.value === "string") {
|
|
1219
|
+
return {
|
|
1220
|
+
status: "OK",
|
|
1221
|
+
...await startPendingEmailVerification({
|
|
1222
|
+
userId: session.getUserId(),
|
|
1223
|
+
recipeUserId: session.getRecipeUserId(),
|
|
1224
|
+
tenantId: session.getTenantId(),
|
|
1225
|
+
email: payload.value,
|
|
1226
|
+
pendingVerificationId: (0, import_crypto.randomUUID)(),
|
|
1227
|
+
userContext: appVariantId ? { ...userContext, rowndAppVariantId: appVariantId } : userContext
|
|
1228
|
+
})
|
|
1229
|
+
};
|
|
1230
|
+
}
|
|
1231
|
+
const permissionError = validateWritableFields([field]);
|
|
1232
|
+
if (permissionError) {
|
|
1233
|
+
return permissionError;
|
|
1234
|
+
}
|
|
1235
|
+
return {
|
|
1236
|
+
status: "OK",
|
|
1237
|
+
...await updateUserData(session.getUserId(), {
|
|
1238
|
+
[field]: payload.value
|
|
1239
|
+
})
|
|
1240
|
+
};
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
function requireSession(session) {
|
|
1244
|
+
if (!session) {
|
|
1245
|
+
throw new Error("Session not found");
|
|
1246
|
+
}
|
|
1247
|
+
return session;
|
|
1248
|
+
}
|
|
1249
|
+
async function getJsonBody(req) {
|
|
1250
|
+
return req.getJSONBody();
|
|
1251
|
+
}
|
|
1252
|
+
function parseGuestBody(value) {
|
|
1253
|
+
if (!isJsonRecord(value)) {
|
|
1254
|
+
return {};
|
|
1255
|
+
}
|
|
1256
|
+
return {
|
|
1257
|
+
authLevel: typeof value.auth_level === "string" ? value.auth_level : void 0
|
|
1258
|
+
};
|
|
1259
|
+
}
|
|
1260
|
+
function parseUpdateUserBody(value) {
|
|
1261
|
+
if (!isJsonRecord(value) || !isJsonRecord(value.data)) {
|
|
1262
|
+
return {};
|
|
1263
|
+
}
|
|
1264
|
+
return {
|
|
1265
|
+
data: value.data,
|
|
1266
|
+
...isJsonRecord(value.context) ? { context: value.context } : {}
|
|
1267
|
+
};
|
|
1268
|
+
}
|
|
1269
|
+
function parseUpdateMetaBody(value) {
|
|
1270
|
+
if (!isJsonRecord(value) || !isJsonRecord(value.meta)) {
|
|
1271
|
+
return {};
|
|
1272
|
+
}
|
|
1273
|
+
return { meta: value.meta };
|
|
1274
|
+
}
|
|
1275
|
+
function parseUpdateFieldBody(value) {
|
|
1276
|
+
if (!isJsonRecord(value) || !hasOwn(value, "value")) {
|
|
1277
|
+
return {};
|
|
1278
|
+
}
|
|
1279
|
+
return { value: value.value };
|
|
1280
|
+
}
|
|
1281
|
+
function validateWritableFields(fields) {
|
|
1282
|
+
const readOnlyField = fields.find((field) => !canUpdateUserDataField(field));
|
|
1283
|
+
if (!readOnlyField) {
|
|
1284
|
+
return void 0;
|
|
1285
|
+
}
|
|
1286
|
+
return {
|
|
1287
|
+
status: "ERROR",
|
|
1288
|
+
code: 403,
|
|
1289
|
+
message: `field is not writable: ${readOnlyField}`
|
|
1290
|
+
};
|
|
1291
|
+
}
|
|
1292
|
+
function missingFieldResponse() {
|
|
1293
|
+
return {
|
|
1294
|
+
status: "ERROR",
|
|
1295
|
+
code: 400,
|
|
1296
|
+
message: "field is required"
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
function isJsonRecord(value) {
|
|
1300
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1301
|
+
}
|
|
1302
|
+
function hasOwn(value, key) {
|
|
1303
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
1304
|
+
}
|
|
1305
|
+
function getErrorMessage(error) {
|
|
1306
|
+
return error instanceof Error ? error.message : "Unknown error";
|
|
1307
|
+
}
|
|
1308
|
+
function mapRowndUserToSuperTokens(rowndUser) {
|
|
1309
|
+
const loginMethods = [];
|
|
1310
|
+
const rowndUserData = rowndUser.data || {};
|
|
1311
|
+
const rowndUserVerifiedData = rowndUser.verified_data || {};
|
|
1312
|
+
if (!rowndUserData.user_id) {
|
|
1313
|
+
throw new Error("Rownd user has no user_id");
|
|
1314
|
+
}
|
|
1315
|
+
if (rowndUserData.google_id) {
|
|
1316
|
+
if (!rowndUserData.email) {
|
|
1317
|
+
throw new Error("Rownd Google user is missing email");
|
|
1318
|
+
}
|
|
1319
|
+
loginMethods.push({
|
|
1320
|
+
recipeId: "thirdparty",
|
|
1321
|
+
thirdPartyId: "google",
|
|
1322
|
+
thirdPartyUserId: rowndUserData.google_id,
|
|
1323
|
+
email: rowndUserData.email,
|
|
1324
|
+
isVerified: !!rowndUserVerifiedData.google_id
|
|
1325
|
+
});
|
|
1326
|
+
}
|
|
1327
|
+
if (rowndUserData.apple_id) {
|
|
1328
|
+
if (!rowndUserData.email) {
|
|
1329
|
+
throw new Error("Rownd Apple user is missing email");
|
|
1330
|
+
}
|
|
1331
|
+
loginMethods.push({
|
|
1332
|
+
recipeId: "thirdparty",
|
|
1333
|
+
thirdPartyId: "apple",
|
|
1334
|
+
thirdPartyUserId: rowndUserData.apple_id,
|
|
1335
|
+
email: rowndUserData.email,
|
|
1336
|
+
isVerified: !!rowndUserVerifiedData.apple_id
|
|
1337
|
+
});
|
|
1338
|
+
}
|
|
1339
|
+
if (rowndUserData.phone_number) {
|
|
1340
|
+
loginMethods.push({
|
|
1341
|
+
recipeId: "passwordless",
|
|
1342
|
+
phoneNumber: rowndUserData.phone_number,
|
|
1343
|
+
isVerified: !!rowndUserVerifiedData.phone_number
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
if (rowndUserData.email && !rowndUserData.google_id && !rowndUserData.apple_id) {
|
|
1347
|
+
loginMethods.push({
|
|
1348
|
+
recipeId: "passwordless",
|
|
1349
|
+
email: rowndUserData.email,
|
|
1350
|
+
isVerified: !!rowndUserVerifiedData.email
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1353
|
+
let authLevel = rowndUser.auth_level;
|
|
1354
|
+
if (loginMethods.length === 0) {
|
|
1355
|
+
const thirdPartyId = authLevel === GUEST_AUTH_METHOD_ID ? GUEST_AUTH_METHOD_ID : ANONYMOUS_AUTH_METHOD_ID;
|
|
1356
|
+
if (!authLevel) authLevel = thirdPartyId;
|
|
1357
|
+
loginMethods.push({
|
|
1358
|
+
recipeId: "thirdparty",
|
|
1359
|
+
thirdPartyId,
|
|
1360
|
+
thirdPartyUserId: rowndUserData.user_id,
|
|
1361
|
+
email: `${rowndUserData.user_id}@anonymous.local`,
|
|
1362
|
+
isVerified: false
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
1365
|
+
const userMetadata = buildRowndUserMetadata(rowndUser);
|
|
1366
|
+
return {
|
|
1367
|
+
externalUserId: rowndUserData.user_id,
|
|
1368
|
+
loginMethods,
|
|
1369
|
+
userMetadata
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1372
|
+
async function importUser(stUser, config2) {
|
|
1373
|
+
const headers = {
|
|
1374
|
+
"Content-Type": "application/json"
|
|
1375
|
+
};
|
|
1376
|
+
if (config2.apiKey) {
|
|
1377
|
+
headers["api-key"] = config2.apiKey;
|
|
1378
|
+
}
|
|
1379
|
+
const response = await fetch(`${config2.connectionURI}/bulk-import/import`, {
|
|
1380
|
+
method: "POST",
|
|
1381
|
+
headers,
|
|
1382
|
+
body: JSON.stringify(stUser)
|
|
1383
|
+
});
|
|
1384
|
+
if (!response.ok) {
|
|
1385
|
+
const errorText = await response.text();
|
|
1386
|
+
throw new Error(
|
|
1387
|
+
`Bulk import failed with status ${response.status}: ${errorText}`
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
const importResponse = await response.json();
|
|
1391
|
+
if (importResponse.status !== "OK" || !importResponse.user) {
|
|
1392
|
+
throw new Error(
|
|
1393
|
+
`Bulk import failed: ${importResponse.message || "Missing user in response"}`
|
|
1394
|
+
);
|
|
1395
|
+
}
|
|
1396
|
+
return importResponse.user;
|
|
1397
|
+
}
|
|
1398
|
+
async function validateRowndToken(token) {
|
|
1399
|
+
const client = getRowndClient();
|
|
1400
|
+
const tokenInfo = await client.validateToken(token);
|
|
1401
|
+
return tokenInfo.user_id;
|
|
1402
|
+
}
|
|
1403
|
+
async function fetchRowndUserInfo(userId) {
|
|
1404
|
+
const client = getRowndClient();
|
|
1405
|
+
const rowndUser = await client.fetchUserInfo({ user_id: userId });
|
|
1406
|
+
if (!rowndUser) {
|
|
1407
|
+
throw new RowndPluginError("ROWND_USER_NOT_FOUND");
|
|
1408
|
+
}
|
|
1409
|
+
return rowndUser;
|
|
1410
|
+
}
|
|
1411
|
+
var IDENTITY_USER_DATA_FIELDS = /* @__PURE__ */ new Set([
|
|
1412
|
+
"user_id",
|
|
1413
|
+
"email",
|
|
1414
|
+
"phone_number",
|
|
1415
|
+
"google_id",
|
|
1416
|
+
"apple_id"
|
|
1417
|
+
]);
|
|
1418
|
+
var INTERNAL_METADATA_FIELDS = /* @__PURE__ */ new Set([
|
|
1419
|
+
"original_rownd_user",
|
|
1420
|
+
"rownd_pending_verification"
|
|
1421
|
+
]);
|
|
1422
|
+
function isIdentityField(field) {
|
|
1423
|
+
return IDENTITY_USER_DATA_FIELDS.has(field);
|
|
1424
|
+
}
|
|
1425
|
+
function isInternalMetadataField(field) {
|
|
1426
|
+
return INTERNAL_METADATA_FIELDS.has(field);
|
|
1427
|
+
}
|
|
1428
|
+
function getStringList(value) {
|
|
1429
|
+
if (Array.isArray(value)) {
|
|
1430
|
+
return value.filter((entry) => typeof entry === "string");
|
|
1431
|
+
}
|
|
1432
|
+
return typeof value === "string" ? [value] : [];
|
|
1433
|
+
}
|
|
1434
|
+
function getRequestedAppVariantIdFromRequest(req) {
|
|
1435
|
+
return req.getKeyValueFromQuery("app_variant_id");
|
|
1436
|
+
}
|
|
1437
|
+
function getRequestedDisplayContextFromRequest(req) {
|
|
1438
|
+
const displayContext = req.getKeyValueFromQuery("rownd_display_context");
|
|
1439
|
+
return displayContext === "browser" || displayContext === "mobile_app" || displayContext === "customer_web_view" ? displayContext : void 0;
|
|
1440
|
+
}
|
|
1441
|
+
function getRequestedRedirectToPathFromRequest(req) {
|
|
1442
|
+
const redirectToPath = req.getKeyValueFromQuery("rownd_redirect_to_path");
|
|
1443
|
+
return typeof redirectToPath === "string" && redirectToPath.length > 0 ? redirectToPath : void 0;
|
|
1444
|
+
}
|
|
1445
|
+
function assertRowndAppVariantIsConfigured(appVariantId) {
|
|
1446
|
+
if (!appVariantId) {
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
if (pluginConfig?.subBrands && !pluginConfig.subBrands[appVariantId]) {
|
|
1450
|
+
throw new Error(`Unknown Rownd app variant: ${appVariantId}`);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
async function recordRowndAppVariantForUser(userId, appVariantId) {
|
|
1454
|
+
if (!appVariantId) {
|
|
1455
|
+
return;
|
|
1456
|
+
}
|
|
1457
|
+
assertRowndAppVariantIsConfigured(appVariantId);
|
|
1458
|
+
const metadata = await getUserMetadata(userId);
|
|
1459
|
+
const originalRowndUser = isJsonRecord(metadata.original_rownd_user) ? metadata.original_rownd_user : {};
|
|
1460
|
+
const attributes = isJsonRecord(originalRowndUser.attributes) ? originalRowndUser.attributes : {};
|
|
1461
|
+
const appVariants = getStringList(attributes["rownd:app_variants"]);
|
|
1462
|
+
if (appVariants.includes(appVariantId)) {
|
|
1463
|
+
return;
|
|
1464
|
+
}
|
|
1465
|
+
await import_usermetadata2.default.updateUserMetadata(userId, {
|
|
1466
|
+
...metadata,
|
|
1467
|
+
original_rownd_user: {
|
|
1468
|
+
...originalRowndUser,
|
|
1469
|
+
data: isJsonRecord(originalRowndUser.data) ? originalRowndUser.data : { user_id: userId },
|
|
1470
|
+
verified_data: isJsonRecord(originalRowndUser.verified_data) ? originalRowndUser.verified_data : {},
|
|
1471
|
+
attributes: {
|
|
1472
|
+
...attributes,
|
|
1473
|
+
"rownd:app_variants": [...appVariants, appVariantId]
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
});
|
|
1477
|
+
}
|
|
1478
|
+
function buildRowndUserMetadata(rowndUser) {
|
|
1479
|
+
const metadata = {
|
|
1480
|
+
...rowndUser.meta || {},
|
|
1481
|
+
original_rownd_user: rowndUser
|
|
1482
|
+
};
|
|
1483
|
+
for (const [key, value] of Object.entries(rowndUser.data || {})) {
|
|
1484
|
+
if (!isIdentityField(key) && value !== void 0) {
|
|
1485
|
+
metadata[key] = value;
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
return metadata;
|
|
1489
|
+
}
|
|
1490
|
+
var RowndIsAnonymousClaim = new import_claims.BooleanClaim({
|
|
1491
|
+
key: "is_anonymous",
|
|
1492
|
+
fetchValue: async (userId) => {
|
|
1493
|
+
const user = await import_supertokens_node.default.getUser(userId);
|
|
1494
|
+
const effectiveAuthLevel = getEffectiveAuthLevel(user);
|
|
1495
|
+
return effectiveAuthLevel === GUEST_AUTH_METHOD_ID;
|
|
1496
|
+
}
|
|
1497
|
+
});
|
|
1498
|
+
async function buildRowndSessionClaims(userId, currentPayload = {}, appVariantId) {
|
|
1499
|
+
const user = await import_supertokens_node.default.getUser(userId);
|
|
1500
|
+
const metadata = user ? await getUserMetadata(user.id) : void 0;
|
|
1501
|
+
const originalRowndUser = metadata?.original_rownd_user;
|
|
1502
|
+
const verifiedData = originalRowndUser?.verified_data;
|
|
1503
|
+
const authLevel = getEffectiveAuthLevel(
|
|
1504
|
+
user,
|
|
1505
|
+
originalRowndUser?.auth_level,
|
|
1506
|
+
verifiedData
|
|
1507
|
+
);
|
|
1508
|
+
const appUserId = getRowndAppUserId(userId, user, currentPayload, metadata);
|
|
1509
|
+
const isAnonymous = authLevel === GUEST_AUTH_METHOD_ID;
|
|
1510
|
+
const anonymousId = getAnonymousId(userId, user, metadata);
|
|
1511
|
+
const isVerifiedUser = authLevel !== "unverified";
|
|
1512
|
+
const audience = buildRowndAudience(currentPayload, appVariantId);
|
|
1513
|
+
const configuredClaims = buildConfiguredSessionClaims(metadata);
|
|
1514
|
+
return {
|
|
1515
|
+
...audience,
|
|
1516
|
+
...configuredClaims,
|
|
1517
|
+
app_user_id: appUserId,
|
|
1518
|
+
auth_level: authLevel,
|
|
1519
|
+
is_verified_user: isVerifiedUser,
|
|
1520
|
+
[ROWND_JWT_CLAIMS.AppUserId]: appUserId,
|
|
1521
|
+
[ROWND_JWT_CLAIMS.AuthLevel]: authLevel,
|
|
1522
|
+
[ROWND_JWT_CLAIMS.IsVerifiedUser]: isVerifiedUser,
|
|
1523
|
+
[ROWND_JWT_CLAIMS.IsAnonymous]: isAnonymous,
|
|
1524
|
+
...anonymousId ? { anonymous_id: anonymousId } : {}
|
|
1525
|
+
};
|
|
1526
|
+
}
|
|
1527
|
+
function buildConfiguredSessionClaims(metadata) {
|
|
1528
|
+
if (!metadata) {
|
|
1529
|
+
return {};
|
|
1530
|
+
}
|
|
1531
|
+
const schema = pluginConfig?.schema || DEFAULT_ROWND_SCHEMA;
|
|
1532
|
+
const claims = {};
|
|
1533
|
+
for (const [key, field] of Object.entries(schema)) {
|
|
1534
|
+
if (field.include_in_session_claims !== true) {
|
|
1535
|
+
continue;
|
|
1536
|
+
}
|
|
1537
|
+
const value = metadata.original_rownd_user?.data?.[key] ?? metadata[key];
|
|
1538
|
+
if (value !== void 0) {
|
|
1539
|
+
claims[field.session_claim_name || key] = value;
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
return claims;
|
|
1543
|
+
}
|
|
1544
|
+
function getRowndAppUserId(userId, user, currentPayload, metadata) {
|
|
1545
|
+
const originalUserId = metadata?.original_rownd_user?.data?.user_id;
|
|
1546
|
+
if (typeof originalUserId === "string") {
|
|
1547
|
+
return originalUserId;
|
|
1548
|
+
}
|
|
1549
|
+
if (typeof currentPayload.app_user_id === "string") {
|
|
1550
|
+
return currentPayload.app_user_id;
|
|
1551
|
+
}
|
|
1552
|
+
return user?.id || userId;
|
|
1553
|
+
}
|
|
1554
|
+
function buildRowndAudience(currentPayload, appVariantId) {
|
|
1555
|
+
const audience = getStringList(currentPayload.aud);
|
|
1556
|
+
const appId = pluginConfig?.appConfig?.id;
|
|
1557
|
+
if (appId) {
|
|
1558
|
+
audience.push(`app:${appId}`);
|
|
1559
|
+
}
|
|
1560
|
+
if (appVariantId) {
|
|
1561
|
+
audience.push(`app_variant:${appVariantId}`);
|
|
1562
|
+
}
|
|
1563
|
+
return audience.length > 0 ? { aud: [...new Set(audience)] } : {};
|
|
1564
|
+
}
|
|
1565
|
+
function getAnonymousId(userId, user, metadata) {
|
|
1566
|
+
const originalAnonymousId = metadata?.original_rownd_user?.data?.anonymous_id;
|
|
1567
|
+
if (typeof originalAnonymousId === "string") {
|
|
1568
|
+
return originalAnonymousId;
|
|
1569
|
+
}
|
|
1570
|
+
const anonymousMethod = user?.loginMethods.find((loginMethod) => {
|
|
1571
|
+
return loginMethod.recipeId === "thirdparty" && getThirdPartyId(loginMethod) === ANONYMOUS_AUTH_METHOD_ID;
|
|
1572
|
+
});
|
|
1573
|
+
const thirdPartyUserId = anonymousMethod ? getThirdPartyUserId(anonymousMethod) : void 0;
|
|
1574
|
+
return thirdPartyUserId || (hasAnonymousLoginMethod(user) ? `anon_${userId}` : void 0);
|
|
1575
|
+
}
|
|
1576
|
+
async function shouldLinkRowndAccounts(input) {
|
|
1577
|
+
const [newAccountInfo, , session] = input;
|
|
1578
|
+
if (!session) {
|
|
1579
|
+
return void 0;
|
|
1580
|
+
}
|
|
1581
|
+
const currentUser = await import_supertokens_node.default.getUser(session.getUserId());
|
|
1582
|
+
if (hasOnlyGuestLoginMethods(currentUser)) {
|
|
1583
|
+
return {
|
|
1584
|
+
shouldAutomaticallyLink: true,
|
|
1585
|
+
shouldRequireVerification: false
|
|
1586
|
+
};
|
|
1587
|
+
}
|
|
1588
|
+
if (!currentUser || isGuestAccountInfo(newAccountInfo)) {
|
|
1589
|
+
return void 0;
|
|
1590
|
+
}
|
|
1591
|
+
if (doesAccountInfoMatchAuthMethod(currentUser, newAccountInfo)) {
|
|
1592
|
+
return {
|
|
1593
|
+
shouldAutomaticallyLink: true,
|
|
1594
|
+
shouldRequireVerification: true
|
|
1595
|
+
};
|
|
1596
|
+
}
|
|
1597
|
+
return void 0;
|
|
1598
|
+
}
|
|
1599
|
+
async function getUserMetadata(userId) {
|
|
1600
|
+
const metadata = await import_usermetadata2.default.getUserMetadata(userId);
|
|
1601
|
+
return metadata.metadata || {};
|
|
1602
|
+
}
|
|
1603
|
+
function getPendingVerifications(metadata) {
|
|
1604
|
+
const pendingVerification = metadata.rownd_pending_verification;
|
|
1605
|
+
if (Array.isArray(pendingVerification)) {
|
|
1606
|
+
return pendingVerification.filter(isPendingVerification);
|
|
1607
|
+
}
|
|
1608
|
+
return [];
|
|
1609
|
+
}
|
|
1610
|
+
function isPendingVerification(value) {
|
|
1611
|
+
return isRecord(value) && typeof value.id === "string" && typeof value.field === "string" && typeof value.value === "string" && typeof value.created_at === "string";
|
|
1612
|
+
}
|
|
1613
|
+
async function getUserById(userId) {
|
|
1614
|
+
const metadata = await getUserMetadata(userId);
|
|
1615
|
+
const stUser = await import_supertokens_node.default.getUser(userId);
|
|
1616
|
+
if (!stUser) {
|
|
1617
|
+
throw new RowndPluginError("ROWND_USER_NOT_FOUND");
|
|
1618
|
+
}
|
|
1619
|
+
const originalRowndUser = metadata.original_rownd_user;
|
|
1620
|
+
const rowndUser = originalRowndUser?.data?.user_id || userId;
|
|
1621
|
+
const state = originalRowndUser?.state || "enabled";
|
|
1622
|
+
const dataFieldKeys = /* @__PURE__ */ new Set();
|
|
1623
|
+
const data = {
|
|
1624
|
+
user_id: userId
|
|
1625
|
+
};
|
|
1626
|
+
for (const [key, value] of Object.entries(originalRowndUser?.data || {})) {
|
|
1627
|
+
if (!isIdentityField(key)) {
|
|
1628
|
+
data[key] = value;
|
|
1629
|
+
dataFieldKeys.add(key);
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
const schema = pluginConfig?.schema || DEFAULT_ROWND_SCHEMA;
|
|
1633
|
+
for (const key of Object.keys(schema)) {
|
|
1634
|
+
dataFieldKeys.add(key);
|
|
1635
|
+
if (!isInternalMetadataField(key) && !isIdentityField(key) && metadata[key] !== void 0) {
|
|
1636
|
+
data[key] = metadata[key];
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
const verifiedData = {
|
|
1640
|
+
...originalRowndUser?.verified_data || {}
|
|
1641
|
+
};
|
|
1642
|
+
let lastUsedAt = stUser.timeJoined;
|
|
1643
|
+
for (const method of stUser.loginMethods) {
|
|
1644
|
+
if (typeof method.lastUsed === "number" && method.lastUsed > lastUsedAt) {
|
|
1645
|
+
lastUsedAt = method.lastUsed;
|
|
1646
|
+
}
|
|
1647
|
+
if (method.recipeId === "passwordless") {
|
|
1648
|
+
if (method.email) {
|
|
1649
|
+
verifiedData.email = method.email;
|
|
1650
|
+
if (data.email === void 0) data.email = method.email;
|
|
1651
|
+
}
|
|
1652
|
+
if (method.phoneNumber) {
|
|
1653
|
+
verifiedData.phone_number = method.phoneNumber;
|
|
1654
|
+
if (data.phone_number === void 0)
|
|
1655
|
+
data.phone_number = method.phoneNumber;
|
|
1656
|
+
}
|
|
1657
|
+
} else if (method.recipeId === "thirdparty") {
|
|
1658
|
+
const thirdPartyId = getThirdPartyId(method);
|
|
1659
|
+
const thirdPartyUserId = getThirdPartyUserId(method);
|
|
1660
|
+
if (method.verified && method.email) {
|
|
1661
|
+
verifiedData.email = method.email;
|
|
1662
|
+
}
|
|
1663
|
+
if (method.email && data.email === void 0) {
|
|
1664
|
+
data.email = method.email;
|
|
1665
|
+
}
|
|
1666
|
+
if (thirdPartyId === "google" && thirdPartyUserId) {
|
|
1667
|
+
data.google_id = thirdPartyUserId;
|
|
1668
|
+
verifiedData.google_id = thirdPartyUserId;
|
|
1669
|
+
}
|
|
1670
|
+
if (thirdPartyId === "apple" && thirdPartyUserId) {
|
|
1671
|
+
data.apple_id = thirdPartyUserId;
|
|
1672
|
+
verifiedData.apple_id = thirdPartyUserId;
|
|
1673
|
+
}
|
|
1674
|
+
} else if (method.recipeId === "emailpassword") {
|
|
1675
|
+
if (method.email && data.email === void 0) {
|
|
1676
|
+
data.email = method.email;
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
if (verifiedData.email === true && typeof data.email === "string") {
|
|
1681
|
+
verifiedData.email = data.email;
|
|
1682
|
+
}
|
|
1683
|
+
if (verifiedData.phone_number === true && typeof data.phone_number === "string") {
|
|
1684
|
+
verifiedData.phone_number = data.phone_number;
|
|
1685
|
+
}
|
|
1686
|
+
const anonymousId = getAnonymousId(stUser.id, stUser, metadata);
|
|
1687
|
+
if (anonymousId && data.anonymous_id === void 0) {
|
|
1688
|
+
data.anonymous_id = anonymousId;
|
|
1689
|
+
}
|
|
1690
|
+
const authLevel = getEffectiveAuthLevel(
|
|
1691
|
+
stUser,
|
|
1692
|
+
originalRowndUser?.auth_level,
|
|
1693
|
+
verifiedData
|
|
1694
|
+
);
|
|
1695
|
+
for (const [key, field] of Object.entries(schema)) {
|
|
1696
|
+
if (data[key] === void 0 && field.type === "string") {
|
|
1697
|
+
data[key] = "";
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
const mapMethod = (method) => {
|
|
1701
|
+
if (method.recipeId === "thirdparty") {
|
|
1702
|
+
if (getThirdPartyId(method) === "google") return "google";
|
|
1703
|
+
if (getThirdPartyId(method) === "apple") return "apple";
|
|
1704
|
+
} else if (method.recipeId === "passwordless") {
|
|
1705
|
+
if (method.email) return "email";
|
|
1706
|
+
if (method.phoneNumber) return "phone";
|
|
1707
|
+
} else if (method.recipeId === "emailpassword") {
|
|
1708
|
+
return "email";
|
|
1709
|
+
}
|
|
1710
|
+
return "email";
|
|
1711
|
+
};
|
|
1712
|
+
const sortedByJoined = [...stUser.loginMethods].sort(
|
|
1713
|
+
(a, b) => a.timeJoined - b.timeJoined
|
|
1714
|
+
);
|
|
1715
|
+
const sortedByLastUsed = [
|
|
1716
|
+
...stUser.loginMethods
|
|
1717
|
+
].sort((a, b) => (b.lastUsed || b.timeJoined) - (a.lastUsed || a.timeJoined));
|
|
1718
|
+
const firstMethod = sortedByJoined[0];
|
|
1719
|
+
const lastMethod = sortedByLastUsed[0];
|
|
1720
|
+
const metadataMeta = Object.fromEntries(
|
|
1721
|
+
Object.entries(metadata).filter(
|
|
1722
|
+
([key]) => !isInternalMetadataField(key) && !dataFieldKeys.has(key)
|
|
1723
|
+
)
|
|
1724
|
+
);
|
|
1725
|
+
const meta = {
|
|
1726
|
+
...metadataMeta,
|
|
1727
|
+
created: new Date(stUser.timeJoined).toISOString(),
|
|
1728
|
+
first_sign_in: new Date(stUser.timeJoined).toISOString(),
|
|
1729
|
+
last_sign_in: new Date(lastUsedAt).toISOString(),
|
|
1730
|
+
last_active: new Date(lastUsedAt).toISOString(),
|
|
1731
|
+
first_sign_in_method: firstMethod ? mapMethod(firstMethod) : "email",
|
|
1732
|
+
last_sign_in_method: lastMethod ? mapMethod(lastMethod) : "email"
|
|
1733
|
+
};
|
|
1734
|
+
return {
|
|
1735
|
+
rownd_user: rowndUser,
|
|
1736
|
+
data,
|
|
1737
|
+
meta,
|
|
1738
|
+
verified_data: verifiedData,
|
|
1739
|
+
state,
|
|
1740
|
+
auth_level: authLevel,
|
|
1741
|
+
redacted: [],
|
|
1742
|
+
groups: originalRowndUser?.groups || [],
|
|
1743
|
+
attributes: originalRowndUser?.attributes || {}
|
|
1744
|
+
};
|
|
1745
|
+
}
|
|
1746
|
+
async function updateUserData(userId, inputData) {
|
|
1747
|
+
const metadata = await getUserMetadata(userId);
|
|
1748
|
+
const updatedMetadata = {
|
|
1749
|
+
...metadata,
|
|
1750
|
+
...inputData
|
|
1751
|
+
};
|
|
1752
|
+
await import_usermetadata2.default.updateUserMetadata(userId, updatedMetadata);
|
|
1753
|
+
return getUserById(userId);
|
|
1754
|
+
}
|
|
1755
|
+
async function startPendingEmailVerification(input) {
|
|
1756
|
+
const metadata = await getUserMetadata(input.userId);
|
|
1757
|
+
const currentEmail = (await getUserById(input.userId)).data.email;
|
|
1758
|
+
if (currentEmail === input.email) {
|
|
1759
|
+
return getUserById(input.userId);
|
|
1760
|
+
}
|
|
1761
|
+
const pendingVerifications = getPendingVerifications(metadata);
|
|
1762
|
+
const pendingEmailVerifications = pendingVerifications.filter(
|
|
1763
|
+
(pendingVerification2) => pendingVerification2.field === "email"
|
|
1764
|
+
);
|
|
1765
|
+
for (const pendingVerification2 of pendingEmailVerifications) {
|
|
1766
|
+
await import_emailverification.default.revokeEmailVerificationTokens(
|
|
1767
|
+
input.tenantId,
|
|
1768
|
+
input.recipeUserId,
|
|
1769
|
+
pendingVerification2.value,
|
|
1770
|
+
input.userContext
|
|
1771
|
+
);
|
|
1772
|
+
}
|
|
1773
|
+
const pendingVerification = {
|
|
1774
|
+
id: input.pendingVerificationId,
|
|
1775
|
+
field: "email",
|
|
1776
|
+
value: input.email,
|
|
1777
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1778
|
+
};
|
|
1779
|
+
await import_usermetadata2.default.updateUserMetadata(input.userId, {
|
|
1780
|
+
...metadata,
|
|
1781
|
+
rownd_pending_verification: [
|
|
1782
|
+
...pendingVerifications.filter(
|
|
1783
|
+
(pendingVerification2) => pendingVerification2.field !== "email"
|
|
1784
|
+
),
|
|
1785
|
+
pendingVerification
|
|
1786
|
+
]
|
|
1787
|
+
});
|
|
1788
|
+
const response = await import_emailverification.default.sendEmailVerificationEmail(
|
|
1789
|
+
input.tenantId,
|
|
1790
|
+
input.userId,
|
|
1791
|
+
input.recipeUserId,
|
|
1792
|
+
input.email,
|
|
1793
|
+
{
|
|
1794
|
+
...input.userContext,
|
|
1795
|
+
rowndPendingVerificationId: pendingVerification.id
|
|
1796
|
+
}
|
|
1797
|
+
);
|
|
1798
|
+
if (response.status === "EMAIL_ALREADY_VERIFIED_ERROR") {
|
|
1799
|
+
await completePendingEmailVerification({
|
|
1800
|
+
recipeUserId: input.recipeUserId,
|
|
1801
|
+
email: input.email,
|
|
1802
|
+
userContext: input.userContext
|
|
1803
|
+
});
|
|
1804
|
+
}
|
|
1805
|
+
return getUserById(input.userId);
|
|
1806
|
+
}
|
|
1807
|
+
async function completePendingEmailVerification(input) {
|
|
1808
|
+
const user = await import_supertokens_node.default.getUser(
|
|
1809
|
+
input.recipeUserId.getAsString(),
|
|
1810
|
+
input.userContext
|
|
1811
|
+
);
|
|
1812
|
+
const userId = user?.id ?? input.recipeUserId.getAsString();
|
|
1813
|
+
const metadata = await getUserMetadata(userId);
|
|
1814
|
+
const pendingVerifications = getPendingVerifications(metadata);
|
|
1815
|
+
const pendingVerification = pendingVerifications.find(
|
|
1816
|
+
(pendingVerification2) => pendingVerification2.field === "email" && pendingVerification2.value === input.email
|
|
1817
|
+
);
|
|
1818
|
+
if (!pendingVerification) {
|
|
1819
|
+
return;
|
|
1820
|
+
}
|
|
1821
|
+
let metadataUserId = userId;
|
|
1822
|
+
const passwordlessEmailMethod = getPasswordlessEmailLoginMethod(user);
|
|
1823
|
+
if (passwordlessEmailMethod) {
|
|
1824
|
+
const updateResult = await import_passwordless.default.updateUser({
|
|
1825
|
+
recipeUserId: passwordlessEmailMethod.recipeUserId,
|
|
1826
|
+
email: input.email,
|
|
1827
|
+
userContext: input.userContext
|
|
1828
|
+
});
|
|
1829
|
+
if (updateResult.status !== "OK") {
|
|
1830
|
+
throw new Error(
|
|
1831
|
+
`Failed to update verified email method: ${updateResult.status}`
|
|
1832
|
+
);
|
|
1833
|
+
}
|
|
1834
|
+
} else if (hasOnlyGuestLoginMethods(user)) {
|
|
1835
|
+
const isPasswordlessSignUpAllowed = await import_accountlinking.default.isSignUpAllowed(
|
|
1836
|
+
PUBLIC_TENANT_ID,
|
|
1837
|
+
{
|
|
1838
|
+
recipeId: "passwordless",
|
|
1839
|
+
email: input.email
|
|
1840
|
+
},
|
|
1841
|
+
true,
|
|
1842
|
+
void 0,
|
|
1843
|
+
input.userContext
|
|
1844
|
+
);
|
|
1845
|
+
if (!isPasswordlessSignUpAllowed) {
|
|
1846
|
+
throw new Error("Passwordless sign up is not allowed for this email");
|
|
1847
|
+
}
|
|
1848
|
+
const passwordlessUser = await import_passwordless.default.signInUp({
|
|
1849
|
+
email: input.email,
|
|
1850
|
+
tenantId: PUBLIC_TENANT_ID,
|
|
1851
|
+
userContext: input.userContext
|
|
1852
|
+
});
|
|
1853
|
+
const primaryUserResult = await import_accountlinking.default.createPrimaryUser(
|
|
1854
|
+
passwordlessUser.recipeUserId,
|
|
1855
|
+
input.userContext
|
|
1856
|
+
);
|
|
1857
|
+
const primaryUserId = primaryUserResult.status === "OK" ? primaryUserResult.user.id : primaryUserResult.status === "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR" ? primaryUserResult.primaryUserId : passwordlessUser.user.id;
|
|
1858
|
+
if (userId !== primaryUserId) {
|
|
1859
|
+
const linkResult = await import_accountlinking.default.linkAccounts(
|
|
1860
|
+
input.recipeUserId,
|
|
1861
|
+
primaryUserId,
|
|
1862
|
+
input.userContext
|
|
1863
|
+
);
|
|
1864
|
+
if (linkResult.status !== "OK") {
|
|
1865
|
+
throw new Error(
|
|
1866
|
+
`Failed to link verified email method: ${linkResult.status}`
|
|
1867
|
+
);
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
metadataUserId = primaryUserId;
|
|
1871
|
+
}
|
|
1872
|
+
const updatedMetadata = {
|
|
1873
|
+
...metadata,
|
|
1874
|
+
...metadata.original_rownd_user ? {
|
|
1875
|
+
original_rownd_user: {
|
|
1876
|
+
...metadata.original_rownd_user,
|
|
1877
|
+
data: {
|
|
1878
|
+
...metadata.original_rownd_user.data,
|
|
1879
|
+
email: input.email
|
|
1880
|
+
},
|
|
1881
|
+
verified_data: {
|
|
1882
|
+
...metadata.original_rownd_user.verified_data,
|
|
1883
|
+
email: input.email
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
} : {},
|
|
1887
|
+
rownd_pending_verification: pendingVerifications.filter(
|
|
1888
|
+
(verification) => verification !== pendingVerification
|
|
1889
|
+
)
|
|
1890
|
+
};
|
|
1891
|
+
await import_usermetadata2.default.updateUserMetadata(metadataUserId, updatedMetadata);
|
|
1892
|
+
}
|
|
1893
|
+
async function updateUserMetadata(userId, inputMeta) {
|
|
1894
|
+
const metadata = await getUserMetadata(userId);
|
|
1895
|
+
const updatedMetadata = {
|
|
1896
|
+
...metadata,
|
|
1897
|
+
...inputMeta
|
|
1898
|
+
};
|
|
1899
|
+
await import_usermetadata2.default.updateUserMetadata(userId, updatedMetadata);
|
|
1900
|
+
return {
|
|
1901
|
+
id: userId,
|
|
1902
|
+
meta: Object.fromEntries(
|
|
1903
|
+
Object.entries(updatedMetadata).filter(
|
|
1904
|
+
([key]) => !isInternalMetadataField(key)
|
|
1905
|
+
)
|
|
1906
|
+
)
|
|
1907
|
+
};
|
|
1908
|
+
}
|
|
1909
|
+
function getThirdPartyId(method) {
|
|
1910
|
+
return method.thirdPartyId || method.thirdParty?.id;
|
|
1911
|
+
}
|
|
1912
|
+
function getThirdPartyUserId(method) {
|
|
1913
|
+
return method.thirdPartyUserId || method.thirdParty?.userId;
|
|
1914
|
+
}
|
|
1915
|
+
function getGuestAuthLevel(user) {
|
|
1916
|
+
const guestMethod = user?.loginMethods.find(isGuestLoginMethod);
|
|
1917
|
+
return guestMethod ? GUEST_AUTH_METHOD_ID : void 0;
|
|
1918
|
+
}
|
|
1919
|
+
function hasAnonymousLoginMethod(user) {
|
|
1920
|
+
return !!user?.loginMethods.some((loginMethod) => {
|
|
1921
|
+
return loginMethod.recipeId === "thirdparty" && getThirdPartyId(loginMethod) === ANONYMOUS_AUTH_METHOD_ID;
|
|
1922
|
+
});
|
|
1923
|
+
}
|
|
1924
|
+
function getPasswordlessEmailLoginMethod(user) {
|
|
1925
|
+
return user?.loginMethods.find((method) => {
|
|
1926
|
+
return method.recipeId === "passwordless" && !!method.email;
|
|
1927
|
+
});
|
|
1928
|
+
}
|
|
1929
|
+
function hasOnlyGuestLoginMethods(user) {
|
|
1930
|
+
return !!user?.loginMethods.length && user.loginMethods.every(isGuestLoginMethod);
|
|
1931
|
+
}
|
|
1932
|
+
function isGuestLoginMethod(method) {
|
|
1933
|
+
const thirdPartyId = getThirdPartyId(method);
|
|
1934
|
+
return method.recipeId === "thirdparty" && (thirdPartyId === GUEST_AUTH_METHOD_ID || thirdPartyId === ANONYMOUS_AUTH_METHOD_ID);
|
|
1935
|
+
}
|
|
1936
|
+
function isGuestAccountInfo(input) {
|
|
1937
|
+
return input?.recipeId === "thirdparty" && (input.thirdParty?.id === GUEST_AUTH_METHOD_ID || input.thirdParty?.id === ANONYMOUS_AUTH_METHOD_ID);
|
|
1938
|
+
}
|
|
1939
|
+
function doesAccountInfoMatchAuthMethod(user, accountInfo) {
|
|
1940
|
+
if (!user) {
|
|
1941
|
+
return false;
|
|
1942
|
+
}
|
|
1943
|
+
const normalizedEmail = accountInfo.email?.toLowerCase();
|
|
1944
|
+
if (normalizedEmail) {
|
|
1945
|
+
return user.loginMethods.some((method) => {
|
|
1946
|
+
if (isGuestLoginMethod(method) || !method.email) {
|
|
1947
|
+
return false;
|
|
1948
|
+
}
|
|
1949
|
+
return method.email.toLowerCase() === normalizedEmail;
|
|
1950
|
+
});
|
|
1951
|
+
}
|
|
1952
|
+
if (accountInfo.phoneNumber) {
|
|
1953
|
+
return user.loginMethods.some((method) => {
|
|
1954
|
+
return !isGuestLoginMethod(method) && method.phoneNumber === accountInfo.phoneNumber;
|
|
1955
|
+
});
|
|
1956
|
+
}
|
|
1957
|
+
return false;
|
|
1958
|
+
}
|
|
1959
|
+
function hasVerifiedRealLoginMethod(user) {
|
|
1960
|
+
return !!user?.loginMethods.some((method) => {
|
|
1961
|
+
if (isGuestLoginMethod(method)) {
|
|
1962
|
+
return false;
|
|
1963
|
+
}
|
|
1964
|
+
if (method.recipeId === "passwordless") {
|
|
1965
|
+
return !!(method.email || method.phoneNumber);
|
|
1966
|
+
}
|
|
1967
|
+
if (method.recipeId === "thirdparty") {
|
|
1968
|
+
return !!getThirdPartyUserId(method) && method.verified === true;
|
|
1969
|
+
}
|
|
1970
|
+
if (method.recipeId === "emailpassword") {
|
|
1971
|
+
return !!method.email && method.verified === true;
|
|
1972
|
+
}
|
|
1973
|
+
return method.verified === true;
|
|
1974
|
+
});
|
|
1975
|
+
}
|
|
1976
|
+
function getEffectiveAuthLevel(user, originalAuthLevel, verifiedData) {
|
|
1977
|
+
if (hasVerifiedRealLoginMethod(user)) {
|
|
1978
|
+
return "verified";
|
|
1979
|
+
}
|
|
1980
|
+
return getGuestAuthLevel(user) || originalAuthLevel || (verifiedData && Object.keys(verifiedData).length > 0 ? "verified" : "unverified");
|
|
1981
|
+
}
|
|
1982
|
+
function canUpdateUserDataField(field) {
|
|
1983
|
+
const schema = pluginConfig?.schema || DEFAULT_ROWND_SCHEMA;
|
|
1984
|
+
const schemaField = schema[field];
|
|
1985
|
+
if (!schemaField) {
|
|
1986
|
+
return false;
|
|
1987
|
+
}
|
|
1988
|
+
const ownedBy = field === "google_id" || field === "apple_id" ? "app" : schemaField.owned_by || "user";
|
|
1989
|
+
return ownedBy !== "app" && schemaField.read_only !== true;
|
|
1990
|
+
}
|
|
1991
|
+
var BUILTIN_SIGN_IN_METHOD_KEYS = [
|
|
1992
|
+
"email",
|
|
1993
|
+
"phone",
|
|
1994
|
+
"google",
|
|
1995
|
+
"apple",
|
|
1996
|
+
"anonymous"
|
|
1997
|
+
];
|
|
1998
|
+
function normalizeSchemaField(key, field) {
|
|
1999
|
+
let ownedBy = field.owned_by;
|
|
2000
|
+
if (key === "google_id" || key === "apple_id") {
|
|
2001
|
+
ownedBy = "app";
|
|
2002
|
+
} else if (!ownedBy) {
|
|
2003
|
+
ownedBy = "user";
|
|
2004
|
+
}
|
|
2005
|
+
return {
|
|
2006
|
+
display_name: field.display_name,
|
|
2007
|
+
type: field.type,
|
|
2008
|
+
owned_by: ownedBy,
|
|
2009
|
+
user_visible: field.user_visible,
|
|
2010
|
+
read_only: field.read_only ?? ownedBy === "app",
|
|
2011
|
+
show_empty: field.show_empty ?? false
|
|
2012
|
+
};
|
|
2013
|
+
}
|
|
2014
|
+
var DEFAULT_PRIMARY_COLOR = "#5b5bd6";
|
|
2015
|
+
function buildSignInMethodsConfig(methodsArray) {
|
|
2016
|
+
const methods = (methodsArray ?? []).reduce(
|
|
2017
|
+
(acc, curr) => {
|
|
2018
|
+
acc[curr.method] = curr;
|
|
2019
|
+
return acc;
|
|
2020
|
+
},
|
|
2021
|
+
{}
|
|
2022
|
+
);
|
|
2023
|
+
const customProviders = Object.fromEntries(
|
|
2024
|
+
Object.entries(methods).filter(([key]) => !BUILTIN_SIGN_IN_METHOD_KEYS.includes(key)).map(([key, val]) => {
|
|
2025
|
+
return val ? [
|
|
2026
|
+
key,
|
|
2027
|
+
{
|
|
2028
|
+
enabled: true,
|
|
2029
|
+
display_name: getStringMethodProperty(val, "displayName") ?? key,
|
|
2030
|
+
icon_light_url: getStringMethodProperty(val, "iconLightUrl"),
|
|
2031
|
+
icon_dark_url: getStringMethodProperty(val, "iconDarkUrl")
|
|
2032
|
+
}
|
|
2033
|
+
] : [key, void 0];
|
|
2034
|
+
}).filter(([, v]) => v !== void 0)
|
|
2035
|
+
);
|
|
2036
|
+
const googleMethod = methods.google;
|
|
2037
|
+
const appleMethod = methods.apple;
|
|
2038
|
+
const anonymousMethod = methods.anonymous;
|
|
2039
|
+
const anonymousType = getAnonymousType(anonymousMethod);
|
|
2040
|
+
const googleOneTap = getOneTapConfig(googleMethod);
|
|
2041
|
+
return {
|
|
2042
|
+
email: { enabled: !!methods.email },
|
|
2043
|
+
phone: { enabled: !!methods.phone },
|
|
2044
|
+
google: {
|
|
2045
|
+
enabled: !!googleMethod,
|
|
2046
|
+
client_id: getStringMethodProperty(googleMethod, "clientId") ?? "",
|
|
2047
|
+
ios_client_id: getStringMethodProperty(googleMethod, "iosClientId") ?? "",
|
|
2048
|
+
scopes: getStringArrayMethodProperty(googleMethod, "scopes") ?? [],
|
|
2049
|
+
...getSignInFasterWithGoogle(googleMethod) ? { sign_in_faster_with_google: getSignInFasterWithGoogle(googleMethod) } : {},
|
|
2050
|
+
one_tap: {
|
|
2051
|
+
browser: {
|
|
2052
|
+
auto_prompt: googleOneTap?.browser?.autoPrompt ?? false,
|
|
2053
|
+
delay: googleOneTap?.browser?.delay ?? 7e3
|
|
2054
|
+
},
|
|
2055
|
+
mobile_app: {
|
|
2056
|
+
auto_prompt: googleOneTap?.mobileApp?.autoPrompt ?? false,
|
|
2057
|
+
delay: googleOneTap?.mobileApp?.delay ?? 7e3
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
},
|
|
2061
|
+
apple: {
|
|
2062
|
+
enabled: !!appleMethod,
|
|
2063
|
+
client_id: getStringMethodProperty(appleMethod, "clientId") ?? ""
|
|
2064
|
+
},
|
|
2065
|
+
anonymous: {
|
|
2066
|
+
enabled: !!anonymousMethod && anonymousType !== "instant",
|
|
2067
|
+
...anonymousMethod && anonymousType !== "instant" ? { type: anonymousType } : {},
|
|
2068
|
+
...anonymousType !== "instant" && getStringMethodProperty(anonymousMethod, "displayName") !== void 0 ? {
|
|
2069
|
+
display_name: getStringMethodProperty(
|
|
2070
|
+
anonymousMethod,
|
|
2071
|
+
"displayName"
|
|
2072
|
+
)
|
|
2073
|
+
} : {},
|
|
2074
|
+
...anonymousType !== "instant" && getStringMethodProperty(anonymousMethod, "iconLightUrl") !== void 0 ? {
|
|
2075
|
+
icon_light_url: getStringMethodProperty(
|
|
2076
|
+
anonymousMethod,
|
|
2077
|
+
"iconLightUrl"
|
|
2078
|
+
)
|
|
2079
|
+
} : {},
|
|
2080
|
+
...anonymousType !== "instant" && getStringMethodProperty(anonymousMethod, "iconDarkUrl") !== void 0 ? {
|
|
2081
|
+
icon_dark_url: getStringMethodProperty(
|
|
2082
|
+
anonymousMethod,
|
|
2083
|
+
"iconDarkUrl"
|
|
2084
|
+
)
|
|
2085
|
+
} : {}
|
|
2086
|
+
},
|
|
2087
|
+
...customProviders
|
|
2088
|
+
};
|
|
2089
|
+
}
|
|
2090
|
+
function isInstantAnonymousMethod(methods) {
|
|
2091
|
+
return (methods ?? []).some(
|
|
2092
|
+
(method) => method.method === "anonymous" && getAnonymousType(method) === "instant"
|
|
2093
|
+
);
|
|
2094
|
+
}
|
|
2095
|
+
function getAnonymousType(method) {
|
|
2096
|
+
const type = getStringMethodProperty(method, "type");
|
|
2097
|
+
return type === "instant" ? "instant" : "guest";
|
|
2098
|
+
}
|
|
2099
|
+
function getSignInFasterWithGoogle(method) {
|
|
2100
|
+
const value = getStringMethodProperty(method, "signInFasterWithGoogle");
|
|
2101
|
+
return value === "enabled" || value === "disabled" ? value : void 0;
|
|
2102
|
+
}
|
|
2103
|
+
function getMethodProperty(method, property) {
|
|
2104
|
+
if (!method) {
|
|
2105
|
+
return void 0;
|
|
2106
|
+
}
|
|
2107
|
+
return method[property];
|
|
2108
|
+
}
|
|
2109
|
+
function getStringMethodProperty(method, property) {
|
|
2110
|
+
const value = getMethodProperty(method, property);
|
|
2111
|
+
return typeof value === "string" ? value : void 0;
|
|
2112
|
+
}
|
|
2113
|
+
function getStringArrayMethodProperty(method, property) {
|
|
2114
|
+
const value = getMethodProperty(method, property);
|
|
2115
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : void 0;
|
|
2116
|
+
}
|
|
2117
|
+
function getOneTapConfig(method) {
|
|
2118
|
+
const oneTap = getMethodProperty(method, "oneTap");
|
|
2119
|
+
if (!isRecord(oneTap)) {
|
|
2120
|
+
return void 0;
|
|
2121
|
+
}
|
|
2122
|
+
return {
|
|
2123
|
+
browser: parseOneTapPlatform(oneTap.browser),
|
|
2124
|
+
mobileApp: parseOneTapPlatform(oneTap.mobileApp)
|
|
2125
|
+
};
|
|
2126
|
+
}
|
|
2127
|
+
function parseOneTapPlatform(value) {
|
|
2128
|
+
if (!isRecord(value)) {
|
|
2129
|
+
return void 0;
|
|
2130
|
+
}
|
|
2131
|
+
return {
|
|
2132
|
+
autoPrompt: typeof value.autoPrompt === "boolean" ? value.autoPrompt : void 0,
|
|
2133
|
+
delay: typeof value.delay === "number" ? value.delay : void 0
|
|
2134
|
+
};
|
|
2135
|
+
}
|
|
2136
|
+
function isRecord(value) {
|
|
2137
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2138
|
+
}
|
|
2139
|
+
function getSubBrandVariant(app) {
|
|
2140
|
+
if (isRecord(app) && isRecord(app.variant) && typeof app.variant.id === "string") {
|
|
2141
|
+
return app.variant;
|
|
2142
|
+
}
|
|
2143
|
+
return void 0;
|
|
2144
|
+
}
|
|
2145
|
+
function mergeConfigInput(base, override) {
|
|
2146
|
+
const result = { ...base };
|
|
2147
|
+
for (const [key, value] of Object.entries(override)) {
|
|
2148
|
+
if (value === void 0) {
|
|
2149
|
+
continue;
|
|
2150
|
+
}
|
|
2151
|
+
const existing = result[key];
|
|
2152
|
+
result[key] = isRecord(existing) && isRecord(value) ? mergeConfigInput(existing, value) : value;
|
|
2153
|
+
}
|
|
2154
|
+
return result;
|
|
2155
|
+
}
|
|
2156
|
+
function buildAppConfig(config2, stConfig, appVariantId) {
|
|
2157
|
+
const userSchema = config2.schema ?? DEFAULT_ROWND_SCHEMA;
|
|
2158
|
+
const baseApp = config2.appConfig ?? {};
|
|
2159
|
+
const subBrand = appVariantId ? config2.subBrands?.[appVariantId] : void 0;
|
|
2160
|
+
const app = appVariantId ? subBrand && mergeConfigInput(baseApp, subBrand) : baseApp;
|
|
2161
|
+
if (!app) {
|
|
2162
|
+
return void 0;
|
|
2163
|
+
}
|
|
2164
|
+
const branding = app.branding ?? {};
|
|
2165
|
+
const auth = app.auth ?? {};
|
|
2166
|
+
const signInMethods = buildSignInMethodsConfig(app.signInMethods);
|
|
2167
|
+
const variant = getSubBrandVariant(app);
|
|
2168
|
+
const finalSchema = { ...userSchema };
|
|
2169
|
+
if (signInMethods.email.enabled && !finalSchema.email) {
|
|
2170
|
+
finalSchema.email = {
|
|
2171
|
+
display_name: "Email",
|
|
2172
|
+
type: "string",
|
|
2173
|
+
user_visible: true
|
|
2174
|
+
};
|
|
2175
|
+
}
|
|
2176
|
+
if (signInMethods.phone.enabled && !finalSchema.phone_number) {
|
|
2177
|
+
finalSchema.phone_number = {
|
|
2178
|
+
display_name: "Phone number",
|
|
2179
|
+
type: "string",
|
|
2180
|
+
user_visible: true
|
|
2181
|
+
};
|
|
2182
|
+
}
|
|
2183
|
+
if (signInMethods.google.enabled && !finalSchema.google_id) {
|
|
2184
|
+
finalSchema.google_id = {
|
|
2185
|
+
display_name: "Google ID",
|
|
2186
|
+
type: "string",
|
|
2187
|
+
user_visible: false
|
|
2188
|
+
};
|
|
2189
|
+
}
|
|
2190
|
+
if (signInMethods.apple.enabled && !finalSchema.apple_id) {
|
|
2191
|
+
finalSchema.apple_id = {
|
|
2192
|
+
display_name: "Apple ID",
|
|
2193
|
+
type: "string",
|
|
2194
|
+
user_visible: false
|
|
2195
|
+
};
|
|
2196
|
+
}
|
|
2197
|
+
return {
|
|
2198
|
+
config_type: appVariantId ? "variant" : "app",
|
|
2199
|
+
...variant ? { variant } : {},
|
|
2200
|
+
app: {
|
|
2201
|
+
id: app.id ?? "",
|
|
2202
|
+
name: app.name ?? stConfig.appInfo.appName,
|
|
2203
|
+
icon: app.icon ?? "",
|
|
2204
|
+
...app.userVerificationFields ? { user_verification_fields: app.userVerificationFields } : {},
|
|
2205
|
+
schema: Object.fromEntries(
|
|
2206
|
+
Object.entries(finalSchema).map(([key, field]) => [
|
|
2207
|
+
key,
|
|
2208
|
+
normalizeSchemaField(key, field)
|
|
2209
|
+
])
|
|
2210
|
+
),
|
|
2211
|
+
config: {
|
|
2212
|
+
...app.capabilities ? { capabilities: app.capabilities } : {},
|
|
2213
|
+
...app.web ? { web: app.web } : {},
|
|
2214
|
+
...app.bottomSheet ? { bottom_sheet: app.bottomSheet } : {},
|
|
2215
|
+
...app.profileStorageVersion ? { profile_storage_version: app.profileStorageVersion } : {},
|
|
2216
|
+
customizations: {
|
|
2217
|
+
primary_color: branding.primaryColor ?? DEFAULT_PRIMARY_COLOR,
|
|
2218
|
+
...branding.logo ? { logo: branding.logo } : {},
|
|
2219
|
+
...branding.logoDarkMode ? { logo_dark_mode: branding.logoDarkMode } : {},
|
|
2220
|
+
...branding.animations ? { animations: branding.animations } : {}
|
|
2221
|
+
},
|
|
2222
|
+
hub: {
|
|
2223
|
+
...app.allowedWebOrigins ? { allowed_web_origins: app.allowedWebOrigins } : {},
|
|
2224
|
+
customizations: {
|
|
2225
|
+
rounded_corners: branding.roundedCorners ?? true,
|
|
2226
|
+
...branding.containerBorderRadius !== void 0 ? { container_border_radius: branding.containerBorderRadius } : {},
|
|
2227
|
+
...branding.placement !== void 0 ? { placement: branding.placement } : {},
|
|
2228
|
+
...branding.hubPrimaryColor !== void 0 ? { primary_color: branding.hubPrimaryColor } : {},
|
|
2229
|
+
...branding.primaryColorDarkMode !== void 0 ? { primary_color_dark_mode: branding.primaryColorDarkMode } : {},
|
|
2230
|
+
...branding.backgroundColor !== void 0 ? { background_color: branding.backgroundColor } : {},
|
|
2231
|
+
...branding.fontFamily !== void 0 ? { font_family: branding.fontFamily } : {},
|
|
2232
|
+
...branding.hideVerificationIcons !== void 0 ? { hide_verification_icons: branding.hideVerificationIcons } : {},
|
|
2233
|
+
visual_swoops: branding.visualSwoops ?? true,
|
|
2234
|
+
blur_background: branding.blurBackground ?? true,
|
|
2235
|
+
...branding.blurBackgroundOpacity !== void 0 ? { blur_background_opacity: branding.blurBackgroundOpacity } : {},
|
|
2236
|
+
...branding.offsetX !== void 0 ? { offset_x: branding.offsetX } : {},
|
|
2237
|
+
...branding.offsetY !== void 0 ? { offset_y: branding.offsetY } : {},
|
|
2238
|
+
...branding.propertyOverrides ? { property_overrides: branding.propertyOverrides } : {},
|
|
2239
|
+
dark_mode: branding.darkMode ?? "auto"
|
|
2240
|
+
},
|
|
2241
|
+
...branding.customScripts ? { custom_scripts: branding.customScripts } : {},
|
|
2242
|
+
...branding.customStyles ? { custom_styles: branding.customStyles } : {},
|
|
2243
|
+
auth: {
|
|
2244
|
+
email: buildAuthEmailConfig(auth.email),
|
|
2245
|
+
...auth.mobile ? { mobile: buildAuthMobileConfig(auth.mobile) } : {},
|
|
2246
|
+
sign_in_methods: signInMethods,
|
|
2247
|
+
additional_fields: auth.additionalFields ?? [],
|
|
2248
|
+
...auth.rememberSignInMethod !== void 0 ? { remember_sign_in_method: auth.rememberSignInMethod } : {},
|
|
2249
|
+
...auth.useExplicitSignUpFlow !== void 0 ? { use_explicit_sign_up_flow: auth.useExplicitSignUpFlow } : {},
|
|
2250
|
+
...auth.allowUnverifiedUsers !== void 0 ? { allow_unverified_users: auth.allowUnverifiedUsers } : {},
|
|
2251
|
+
...auth.primarySignUpMethod ? { primary_sign_up_method: auth.primarySignUpMethod } : {},
|
|
2252
|
+
...auth.preferredMethod ? { preferred_method: auth.preferredMethod } : {},
|
|
2253
|
+
...auth.order ? { order: auth.order } : {},
|
|
2254
|
+
...isInstantAnonymousMethod(app.signInMethods) ? { instant_user: { enabled: true } } : {},
|
|
2255
|
+
show_app_icon: branding.showAppIcon ?? false
|
|
2256
|
+
},
|
|
2257
|
+
legal: {
|
|
2258
|
+
...app.legal?.companyName ? { company_name: app.legal.companyName } : {},
|
|
2259
|
+
...app.legal?.privacyPolicyUrl ? { privacy_policy_url: app.legal.privacyPolicyUrl } : {},
|
|
2260
|
+
...app.legal?.termsConditionsUrl ? { terms_conditions_url: app.legal.termsConditionsUrl } : {},
|
|
2261
|
+
...app.legal?.supportEmail ? { support_email: app.legal.supportEmail } : {}
|
|
2262
|
+
},
|
|
2263
|
+
custom_content: {
|
|
2264
|
+
...app.customContent?.signInModal ? {
|
|
2265
|
+
sign_in_modal: {
|
|
2266
|
+
...app.customContent.signInModal.title ? { title: app.customContent.signInModal.title } : {},
|
|
2267
|
+
...app.customContent.signInModal.subtitle ? { subtitle: app.customContent.signInModal.subtitle } : {},
|
|
2268
|
+
...app.customContent.signInModal.signInTitle ? {
|
|
2269
|
+
sign_in_title: app.customContent.signInModal.signInTitle
|
|
2270
|
+
} : {},
|
|
2271
|
+
...app.customContent.signInModal.signUpTitle ? {
|
|
2272
|
+
sign_up_title: app.customContent.signInModal.signUpTitle
|
|
2273
|
+
} : {},
|
|
2274
|
+
...app.customContent.signInModal.signInSubtitle ? {
|
|
2275
|
+
sign_in_subtitle: app.customContent.signInModal.signInSubtitle
|
|
2276
|
+
} : {},
|
|
2277
|
+
...app.customContent.signInModal.signUpSubtitle ? {
|
|
2278
|
+
sign_up_subtitle: app.customContent.signInModal.signUpSubtitle
|
|
2279
|
+
} : {},
|
|
2280
|
+
...app.customContent.signInModal.signInButton ? {
|
|
2281
|
+
sign_in_button: app.customContent.signInModal.signInButton
|
|
2282
|
+
} : {},
|
|
2283
|
+
...app.customContent.signInModal.signUpButton ? {
|
|
2284
|
+
sign_up_button: app.customContent.signInModal.signUpButton
|
|
2285
|
+
} : {}
|
|
2286
|
+
}
|
|
2287
|
+
} : {},
|
|
2288
|
+
...app.customContent?.profileModal ? { profile_modal: app.customContent.profileModal } : {},
|
|
2289
|
+
...app.customContent?.verificationModal ? {
|
|
2290
|
+
verification_modal: {
|
|
2291
|
+
...app.customContent.verificationModal.title ? { title: app.customContent.verificationModal.title } : {},
|
|
2292
|
+
...app.customContent.verificationModal.subtitle ? { subtitle: app.customContent.verificationModal.subtitle } : {}
|
|
2293
|
+
}
|
|
2294
|
+
} : {},
|
|
2295
|
+
...app.customContent?.signInFailureModal ? {
|
|
2296
|
+
sign_in_failure_modal: {
|
|
2297
|
+
failure_message: app.customContent.signInFailureModal.failureMessage
|
|
2298
|
+
}
|
|
2299
|
+
} : {},
|
|
2300
|
+
...app.customContent?.noAccountMessage ? { no_account_message: app.customContent.noAccountMessage } : {},
|
|
2301
|
+
...app.customContent?.mobile ? { mobile: app.customContent.mobile } : {}
|
|
2302
|
+
},
|
|
2303
|
+
profile: {
|
|
2304
|
+
...app.profile?.accountInformation ? { account_information: app.profile.accountInformation } : {},
|
|
2305
|
+
...app.profile?.personalInformation ? { personal_information: app.profile.personalInformation } : {},
|
|
2306
|
+
...app.profile?.preferences ? { preferences: app.profile.preferences } : {},
|
|
2307
|
+
...app.profile?.signOutButton ? { sign_out_button: app.profile.signOutButton } : {},
|
|
2308
|
+
...app.profile?.deleteAccountButton ? { delete_account_button: app.profile.deleteAccountButton } : {},
|
|
2309
|
+
...app.profile?.addSignInMethodsButton ? { add_sign_in_methods_button: app.profile.addSignInMethodsButton } : {}
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
};
|
|
2315
|
+
}
|
|
2316
|
+
function buildAuthEmailConfig(authEmail) {
|
|
2317
|
+
return {
|
|
2318
|
+
from_address: authEmail?.fromAddress ?? "no-reply@rownd.io",
|
|
2319
|
+
image: authEmail?.image ?? "",
|
|
2320
|
+
...authEmail?.subject ? { subject: authEmail.subject } : {},
|
|
2321
|
+
...authEmail?.callToActionText ? { call_to_action_text: authEmail.callToActionText } : {},
|
|
2322
|
+
...authEmail?.verifyTemplate ? { verify_template: authEmail.verifyTemplate } : {},
|
|
2323
|
+
...authEmail?.customContent ? { custom_content: authEmail.customContent } : {},
|
|
2324
|
+
...authEmail?.customClosingContent ? { custom_closing_content: authEmail.customClosingContent } : {}
|
|
2325
|
+
};
|
|
2326
|
+
}
|
|
2327
|
+
function buildAuthMobileConfig(authMobile) {
|
|
2328
|
+
return {
|
|
2329
|
+
...authMobile?.title ? { title: authMobile.title } : {},
|
|
2330
|
+
...authMobile?.image ? { image: authMobile.image } : {},
|
|
2331
|
+
...authMobile?.callToActionText ? { call_to_action_text: authMobile.callToActionText } : {},
|
|
2332
|
+
...authMobile?.hyperlinkText ? { hyperlink_text: authMobile.hyperlinkText } : {},
|
|
2333
|
+
...authMobile?.hyperlinkRedirectUrl ? { hyperlink_redirect_url: authMobile.hyperlinkRedirectUrl } : {},
|
|
2334
|
+
...authMobile?.customContent ? { custom_content: authMobile.customContent } : {}
|
|
2335
|
+
};
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
// src/plugin.ts
|
|
2339
|
+
var init = createPluginInitFunction(
|
|
2340
|
+
(pluginConfig2) => {
|
|
2341
|
+
const rowndClient2 = (0, import_node.createInstance)({
|
|
2342
|
+
app_key: pluginConfig2.rowndAppKey,
|
|
2343
|
+
app_secret: pluginConfig2.rowndAppSecret
|
|
2344
|
+
});
|
|
2345
|
+
const telemetryClient = createClient(pluginConfig2.telemetry);
|
|
2346
|
+
let hubBootstrapParams;
|
|
2347
|
+
const addHubBootstrapParams = (input, linkKey, targetPath) => {
|
|
2348
|
+
const appVariantId = input?.userContext?.rowndAppVariantId;
|
|
2349
|
+
const displayContext = input?.userContext?.rowndDisplayContext;
|
|
2350
|
+
const redirectToPath = input?.userContext?.rowndRedirectToPath;
|
|
2351
|
+
const bootstrapParams = {
|
|
2352
|
+
appKey: pluginConfig2.rowndAppKey,
|
|
2353
|
+
...hubBootstrapParams ?? {},
|
|
2354
|
+
...typeof appVariantId === "string" ? { appVariantId } : {},
|
|
2355
|
+
...typeof displayContext === "string" ? { displayContext } : {},
|
|
2356
|
+
...typeof redirectToPath === "string" ? { redirectToPath } : {}
|
|
2357
|
+
};
|
|
2358
|
+
return {
|
|
2359
|
+
...input,
|
|
2360
|
+
[linkKey]: input[linkKey] ? rewriteLinkPath(input[linkKey], targetPath, bootstrapParams) : input[linkKey]
|
|
2361
|
+
};
|
|
2362
|
+
};
|
|
2363
|
+
setRowndClient(rowndClient2);
|
|
2364
|
+
setPluginConfig(pluginConfig2);
|
|
2365
|
+
if (pluginConfig2.enableDebugLogs) {
|
|
2366
|
+
enableDebugLogs();
|
|
2367
|
+
}
|
|
2368
|
+
logDebugMessage("Rownd plugin init complete");
|
|
2369
|
+
return {
|
|
2370
|
+
id: PLUGIN_ID,
|
|
2371
|
+
compatibleSDKVersions: PLUGIN_SDK_VERSION,
|
|
2372
|
+
init: async () => {
|
|
2373
|
+
if (!import_supertokens_node2.default.isRecipeInitialized("session")) {
|
|
2374
|
+
console.warn(
|
|
2375
|
+
"RowndMigrationPlugin: Session recipe is not initialized. Session migration will fail."
|
|
2376
|
+
);
|
|
2377
|
+
}
|
|
2378
|
+
if (!import_supertokens_node2.default.isRecipeInitialized("thirdparty")) {
|
|
2379
|
+
console.warn(
|
|
2380
|
+
"RowndMigrationPlugin: ThirdParty recipe is not initialized. Guest login will fail."
|
|
2381
|
+
);
|
|
2382
|
+
}
|
|
2383
|
+
if (!import_supertokens_node2.default.isRecipeInitialized("emailverification")) {
|
|
2384
|
+
console.warn(
|
|
2385
|
+
"RowndMigrationPlugin: EmailVerification recipe is not initialized. Verified email profile updates will fail."
|
|
2386
|
+
);
|
|
2387
|
+
}
|
|
2388
|
+
},
|
|
2389
|
+
routeHandlers(stConfig) {
|
|
2390
|
+
const apiBasePath = stConfig.appInfo.apiBasePath.getAsStringDangerous();
|
|
2391
|
+
hubBootstrapParams = {
|
|
2392
|
+
apiDomain: stConfig.appInfo.apiDomain.getAsStringDangerous(),
|
|
2393
|
+
apiBasePath
|
|
2394
|
+
};
|
|
2395
|
+
const routeHandlerDeps = {
|
|
2396
|
+
pluginConfig: pluginConfig2,
|
|
2397
|
+
stConfig,
|
|
2398
|
+
telemetryClient
|
|
2399
|
+
};
|
|
2400
|
+
return {
|
|
2401
|
+
status: "OK",
|
|
2402
|
+
routeHandlers: [
|
|
2403
|
+
{
|
|
2404
|
+
path: `${apiBasePath}${HANDLE_BASE_PATH}/app-config`,
|
|
2405
|
+
method: "get",
|
|
2406
|
+
handler: withRequestHandler(
|
|
2407
|
+
handleGetAppConfig(routeHandlerDeps)
|
|
2408
|
+
)
|
|
2409
|
+
},
|
|
2410
|
+
{
|
|
2411
|
+
path: `${apiBasePath}${HANDLE_BASE_PATH}/guest`,
|
|
2412
|
+
method: "post",
|
|
2413
|
+
handler: withRequestHandler(handleGuestLogin(routeHandlerDeps))
|
|
2414
|
+
},
|
|
2415
|
+
{
|
|
2416
|
+
path: `${apiBasePath}${HANDLE_BASE_PATH}/migrate`,
|
|
2417
|
+
method: "post",
|
|
2418
|
+
handler: withRequestHandler(handleMigrate(routeHandlerDeps))
|
|
2419
|
+
},
|
|
2420
|
+
{
|
|
2421
|
+
path: `${apiBasePath}/plugin/migrate-session`,
|
|
2422
|
+
method: "post",
|
|
2423
|
+
handler: withRequestHandler(handleMigrate(routeHandlerDeps))
|
|
2424
|
+
},
|
|
2425
|
+
{
|
|
2426
|
+
path: `${apiBasePath}${HANDLE_BASE_PATH}/signout`,
|
|
2427
|
+
method: "post",
|
|
2428
|
+
verifySessionOptions: {
|
|
2429
|
+
sessionRequired: true,
|
|
2430
|
+
checkDatabase: true
|
|
2431
|
+
},
|
|
2432
|
+
handler: withRequestHandler(handleSignOut())
|
|
2433
|
+
},
|
|
2434
|
+
{
|
|
2435
|
+
path: `${apiBasePath}${HANDLE_BASE_PATH}/user`,
|
|
2436
|
+
method: "get",
|
|
2437
|
+
verifySessionOptions: { sessionRequired: true },
|
|
2438
|
+
handler: withRequestHandler(handleGetUser())
|
|
2439
|
+
},
|
|
2440
|
+
{
|
|
2441
|
+
path: `${apiBasePath}${HANDLE_BASE_PATH}/user`,
|
|
2442
|
+
method: "put",
|
|
2443
|
+
verifySessionOptions: { sessionRequired: true },
|
|
2444
|
+
handler: withRequestHandler(handleUpdateUser())
|
|
2445
|
+
},
|
|
2446
|
+
{
|
|
2447
|
+
path: `${apiBasePath}${HANDLE_BASE_PATH}/user`,
|
|
2448
|
+
method: "delete",
|
|
2449
|
+
verifySessionOptions: { sessionRequired: true },
|
|
2450
|
+
handler: withRequestHandler(handleDeleteUser())
|
|
2451
|
+
},
|
|
2452
|
+
{
|
|
2453
|
+
path: `${apiBasePath}${HANDLE_BASE_PATH}/user/meta`,
|
|
2454
|
+
method: "get",
|
|
2455
|
+
verifySessionOptions: { sessionRequired: true },
|
|
2456
|
+
handler: withRequestHandler(handleGetUserMeta())
|
|
2457
|
+
},
|
|
2458
|
+
{
|
|
2459
|
+
path: `${apiBasePath}${HANDLE_BASE_PATH}/user/meta`,
|
|
2460
|
+
method: "put",
|
|
2461
|
+
verifySessionOptions: { sessionRequired: true },
|
|
2462
|
+
handler: withRequestHandler(handleUpdateUserMeta())
|
|
2463
|
+
},
|
|
2464
|
+
{
|
|
2465
|
+
path: `${apiBasePath}${HANDLE_BASE_PATH}/user/field`,
|
|
2466
|
+
method: "get",
|
|
2467
|
+
verifySessionOptions: { sessionRequired: true },
|
|
2468
|
+
handler: withRequestHandler(handleGetUserField())
|
|
2469
|
+
},
|
|
2470
|
+
{
|
|
2471
|
+
path: `${apiBasePath}${HANDLE_BASE_PATH}/user/field`,
|
|
2472
|
+
method: "put",
|
|
2473
|
+
verifySessionOptions: { sessionRequired: true },
|
|
2474
|
+
handler: withRequestHandler(handleUpdateUserField())
|
|
2475
|
+
}
|
|
2476
|
+
]
|
|
2477
|
+
};
|
|
2478
|
+
},
|
|
2479
|
+
overrideMap: {
|
|
2480
|
+
passwordless: {
|
|
2481
|
+
config: (config2) => {
|
|
2482
|
+
const originalEmailDeliveryOverride = config2.emailDelivery?.override;
|
|
2483
|
+
const originalSmsDeliveryOverride = config2.smsDelivery?.override;
|
|
2484
|
+
return {
|
|
2485
|
+
...config2,
|
|
2486
|
+
emailDelivery: {
|
|
2487
|
+
...config2.emailDelivery,
|
|
2488
|
+
override: (originalImplementation, builder) => {
|
|
2489
|
+
const implementation = originalEmailDeliveryOverride ? originalEmailDeliveryOverride(
|
|
2490
|
+
originalImplementation,
|
|
2491
|
+
builder
|
|
2492
|
+
) : originalImplementation;
|
|
2493
|
+
return {
|
|
2494
|
+
...implementation,
|
|
2495
|
+
sendEmail: async function(input) {
|
|
2496
|
+
return implementation.sendEmail({
|
|
2497
|
+
...addHubBootstrapParams(
|
|
2498
|
+
input,
|
|
2499
|
+
"urlWithLinkCode",
|
|
2500
|
+
"account/login"
|
|
2501
|
+
)
|
|
2502
|
+
});
|
|
2503
|
+
}
|
|
2504
|
+
};
|
|
2505
|
+
}
|
|
2506
|
+
},
|
|
2507
|
+
smsDelivery: {
|
|
2508
|
+
...config2.smsDelivery,
|
|
2509
|
+
override: (originalImplementation, builder) => {
|
|
2510
|
+
const implementation = originalSmsDeliveryOverride ? originalSmsDeliveryOverride(
|
|
2511
|
+
originalImplementation,
|
|
2512
|
+
builder
|
|
2513
|
+
) : originalImplementation;
|
|
2514
|
+
return {
|
|
2515
|
+
...implementation,
|
|
2516
|
+
sendSms: async function(input) {
|
|
2517
|
+
return implementation.sendSms({
|
|
2518
|
+
...addHubBootstrapParams(
|
|
2519
|
+
input,
|
|
2520
|
+
"urlWithLinkCode",
|
|
2521
|
+
"account/login"
|
|
2522
|
+
)
|
|
2523
|
+
});
|
|
2524
|
+
}
|
|
2525
|
+
};
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
};
|
|
2529
|
+
},
|
|
2530
|
+
apis: (originalImplementation) => ({
|
|
2531
|
+
...originalImplementation,
|
|
2532
|
+
createCodePOST: async (input) => {
|
|
2533
|
+
if (originalImplementation.createCodePOST === void 0) {
|
|
2534
|
+
throw new Error("Passwordless createCodePOST is unavailable");
|
|
2535
|
+
}
|
|
2536
|
+
const displayContext = getRequestedDisplayContextFromRequest(
|
|
2537
|
+
input.options.req
|
|
2538
|
+
);
|
|
2539
|
+
const redirectToPath = getRequestedRedirectToPathFromRequest(
|
|
2540
|
+
input.options.req
|
|
2541
|
+
);
|
|
2542
|
+
const appVariantId = getRequestedAppVariantIdFromRequest(
|
|
2543
|
+
input.options.req
|
|
2544
|
+
);
|
|
2545
|
+
assertRowndAppVariantIsConfigured(appVariantId);
|
|
2546
|
+
return originalImplementation.createCodePOST({
|
|
2547
|
+
...input,
|
|
2548
|
+
userContext: displayContext || redirectToPath || appVariantId ? {
|
|
2549
|
+
...input.userContext,
|
|
2550
|
+
...appVariantId ? { rowndAppVariantId: appVariantId } : {},
|
|
2551
|
+
...displayContext ? { rowndDisplayContext: displayContext } : {},
|
|
2552
|
+
...redirectToPath ? { rowndRedirectToPath: redirectToPath } : {}
|
|
2553
|
+
} : input.userContext
|
|
2554
|
+
});
|
|
2555
|
+
},
|
|
2556
|
+
consumeCodePOST: async (input) => {
|
|
2557
|
+
if (originalImplementation.consumeCodePOST === void 0) {
|
|
2558
|
+
throw new Error(
|
|
2559
|
+
"Passwordless consumeCodePOST is unavailable"
|
|
2560
|
+
);
|
|
2561
|
+
}
|
|
2562
|
+
const appVariantId = getRequestedAppVariantIdFromRequest(
|
|
2563
|
+
input.options.req
|
|
2564
|
+
);
|
|
2565
|
+
assertRowndAppVariantIsConfigured(appVariantId);
|
|
2566
|
+
const response = await originalImplementation.consumeCodePOST({
|
|
2567
|
+
...input,
|
|
2568
|
+
userContext: appVariantId ? { ...input.userContext, rowndAppVariantId: appVariantId } : input.userContext
|
|
2569
|
+
});
|
|
2570
|
+
if (response.status === "OK") {
|
|
2571
|
+
await recordRowndAppVariantForUser(
|
|
2572
|
+
response.user.id,
|
|
2573
|
+
appVariantId
|
|
2574
|
+
);
|
|
2575
|
+
}
|
|
2576
|
+
return response;
|
|
2577
|
+
}
|
|
2578
|
+
})
|
|
2579
|
+
},
|
|
2580
|
+
thirdparty: {
|
|
2581
|
+
apis: (originalImplementation) => ({
|
|
2582
|
+
...originalImplementation,
|
|
2583
|
+
signInUpPOST: async (input) => {
|
|
2584
|
+
if (originalImplementation.signInUpPOST === void 0) {
|
|
2585
|
+
throw new Error("ThirdParty signInUpPOST is unavailable");
|
|
2586
|
+
}
|
|
2587
|
+
const appVariantId = getRequestedAppVariantIdFromRequest(
|
|
2588
|
+
input.options.req
|
|
2589
|
+
);
|
|
2590
|
+
assertRowndAppVariantIsConfigured(appVariantId);
|
|
2591
|
+
const response = await originalImplementation.signInUpPOST({
|
|
2592
|
+
...input,
|
|
2593
|
+
userContext: appVariantId ? { ...input.userContext, rowndAppVariantId: appVariantId } : input.userContext
|
|
2594
|
+
});
|
|
2595
|
+
if (response.status === "OK") {
|
|
2596
|
+
await recordRowndAppVariantForUser(
|
|
2597
|
+
response.user.id,
|
|
2598
|
+
appVariantId
|
|
2599
|
+
);
|
|
2600
|
+
}
|
|
2601
|
+
return response;
|
|
2602
|
+
}
|
|
2603
|
+
})
|
|
2604
|
+
},
|
|
2605
|
+
accountlinking: {
|
|
2606
|
+
recipeInitRequired: true,
|
|
2607
|
+
config: (config2) => {
|
|
2608
|
+
const originalShouldDoAutomaticAccountLinking = config2.shouldDoAutomaticAccountLinking;
|
|
2609
|
+
return {
|
|
2610
|
+
...config2,
|
|
2611
|
+
shouldDoAutomaticAccountLinking: async (...input) => {
|
|
2612
|
+
const rowndLinkingDecision = await shouldLinkRowndAccounts(input);
|
|
2613
|
+
if (rowndLinkingDecision) {
|
|
2614
|
+
return rowndLinkingDecision;
|
|
2615
|
+
}
|
|
2616
|
+
if (originalShouldDoAutomaticAccountLinking) {
|
|
2617
|
+
return originalShouldDoAutomaticAccountLinking(...input);
|
|
2618
|
+
}
|
|
2619
|
+
return {
|
|
2620
|
+
shouldAutomaticallyLink: false,
|
|
2621
|
+
shouldRequireVerification: false
|
|
2622
|
+
};
|
|
2623
|
+
}
|
|
2624
|
+
};
|
|
2625
|
+
}
|
|
2626
|
+
},
|
|
2627
|
+
session: {
|
|
2628
|
+
recipeInitRequired: true,
|
|
2629
|
+
functions: (originalImplementation) => ({
|
|
2630
|
+
...originalImplementation,
|
|
2631
|
+
createNewSession: async (input) => {
|
|
2632
|
+
input.accessTokenPayload = {
|
|
2633
|
+
...input.accessTokenPayload,
|
|
2634
|
+
...await buildRowndSessionClaims(
|
|
2635
|
+
input.userId,
|
|
2636
|
+
input.accessTokenPayload
|
|
2637
|
+
),
|
|
2638
|
+
...await RowndIsAnonymousClaim.build(
|
|
2639
|
+
input.userId,
|
|
2640
|
+
input.recipeUserId,
|
|
2641
|
+
input.tenantId,
|
|
2642
|
+
input.accessTokenPayload,
|
|
2643
|
+
input.userContext
|
|
2644
|
+
)
|
|
2645
|
+
};
|
|
2646
|
+
return originalImplementation.createNewSession(input);
|
|
2647
|
+
}
|
|
2648
|
+
})
|
|
2649
|
+
},
|
|
2650
|
+
emailverification: {
|
|
2651
|
+
recipeInitRequired: true,
|
|
2652
|
+
config: (config2) => {
|
|
2653
|
+
const originalEmailDeliveryOverride = config2.emailDelivery?.override;
|
|
2654
|
+
return {
|
|
2655
|
+
...config2,
|
|
2656
|
+
emailDelivery: {
|
|
2657
|
+
...config2.emailDelivery,
|
|
2658
|
+
override: (originalImplementation, builder) => {
|
|
2659
|
+
const implementation = originalEmailDeliveryOverride ? originalEmailDeliveryOverride(
|
|
2660
|
+
originalImplementation,
|
|
2661
|
+
builder
|
|
2662
|
+
) : originalImplementation;
|
|
2663
|
+
return {
|
|
2664
|
+
...implementation,
|
|
2665
|
+
sendEmail: async (input) => {
|
|
2666
|
+
return implementation.sendEmail({
|
|
2667
|
+
...addHubBootstrapParams(
|
|
2668
|
+
input,
|
|
2669
|
+
"emailVerifyLink",
|
|
2670
|
+
"account/verify-email"
|
|
2671
|
+
)
|
|
2672
|
+
});
|
|
2673
|
+
}
|
|
2674
|
+
};
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
};
|
|
2678
|
+
},
|
|
2679
|
+
apis: (originalImplementation) => ({
|
|
2680
|
+
...originalImplementation,
|
|
2681
|
+
verifyEmailPOST: async (input) => {
|
|
2682
|
+
if (originalImplementation.verifyEmailPOST === void 0) {
|
|
2683
|
+
throw new Error(
|
|
2684
|
+
"EmailVerification verifyEmailPOST is unavailable"
|
|
2685
|
+
);
|
|
2686
|
+
}
|
|
2687
|
+
const response = await originalImplementation.verifyEmailPOST(input);
|
|
2688
|
+
if (response.status === "OK") {
|
|
2689
|
+
await completePendingEmailVerification({
|
|
2690
|
+
recipeUserId: response.user.recipeUserId,
|
|
2691
|
+
email: response.user.email,
|
|
2692
|
+
userContext: input.userContext
|
|
2693
|
+
});
|
|
2694
|
+
}
|
|
2695
|
+
return response;
|
|
2696
|
+
}
|
|
2697
|
+
})
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
};
|
|
2701
|
+
},
|
|
2702
|
+
() => ({}),
|
|
2703
|
+
(config2) => {
|
|
2704
|
+
if (!config2?.rowndAppKey || !config2?.rowndAppSecret) {
|
|
2705
|
+
throw new Error(
|
|
2706
|
+
"Missing rowndAppKey or rowndAppSecret in plugin config"
|
|
2707
|
+
);
|
|
2708
|
+
}
|
|
2709
|
+
if (config2.telemetry?.provider === "axiom") {
|
|
2710
|
+
if (!config2.telemetry.token || !config2.telemetry.dataset) {
|
|
2711
|
+
throw new Error(
|
|
2712
|
+
"Missing telemetry axiom token or dataset in plugin config"
|
|
2713
|
+
);
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
if (config2.telemetry?.provider === "custom") {
|
|
2717
|
+
if (typeof config2.telemetry.factory !== "function") {
|
|
2718
|
+
throw new Error(
|
|
2719
|
+
"Missing telemetry custom factory function in plugin config"
|
|
2720
|
+
);
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
return {
|
|
2724
|
+
rowndAppKey: config2.rowndAppKey,
|
|
2725
|
+
rowndAppSecret: config2.rowndAppSecret,
|
|
2726
|
+
enableDebugLogs: config2.enableDebugLogs,
|
|
2727
|
+
telemetry: config2.telemetry,
|
|
2728
|
+
schema: config2.schema,
|
|
2729
|
+
appConfig: config2.appConfig,
|
|
2730
|
+
subBrands: config2.subBrands
|
|
2731
|
+
};
|
|
2732
|
+
}
|
|
2733
|
+
);
|
|
2734
|
+
|
|
2735
|
+
// src/index.ts
|
|
2736
|
+
var index_default = { init };
|
|
2737
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2738
|
+
0 && (module.exports = {
|
|
2739
|
+
ANONYMOUS_AUTH_METHOD_ID,
|
|
2740
|
+
DEFAULT_ROWND_SCHEMA,
|
|
2741
|
+
GUEST_AUTH_METHOD_ID,
|
|
2742
|
+
HANDLE_BASE_PATH,
|
|
2743
|
+
PLUGIN_ID,
|
|
2744
|
+
PLUGIN_SDK_VERSION,
|
|
2745
|
+
PUBLIC_TENANT_ID,
|
|
2746
|
+
ROWND_JWT_CLAIMS,
|
|
2747
|
+
ROWND_PLUGIN_ERROR_MESSAGES,
|
|
2748
|
+
RowndPluginError,
|
|
2749
|
+
getRowndClient,
|
|
2750
|
+
init,
|
|
2751
|
+
setRowndClient
|
|
2752
|
+
});
|