powr-sdk-web 6.2.0 → 6.3.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.
@@ -43,6 +43,10 @@ var PowrLogin = function PowrLogin(_ref) {
43
43
  requirePhoneVerification = _ref$requirePhoneVeri === void 0 ? true : _ref$requirePhoneVeri,
44
44
  _ref$showForgotPasswo = _ref.showForgotPassword,
45
45
  showForgotPassword = _ref$showForgotPasswo === void 0 ? true : _ref$showForgotPasswo,
46
+ _ref$passwordResetHel = _ref.passwordResetHelpUrl,
47
+ passwordResetHelpUrl = _ref$passwordResetHel === void 0 ? null : _ref$passwordResetHel,
48
+ _ref$passwordResetHel2 = _ref.passwordResetHelpLabel,
49
+ passwordResetHelpLabel = _ref$passwordResetHel2 === void 0 ? 'Forgot password? WhatsApp us' : _ref$passwordResetHel2,
46
50
  _ref$completeProfileO = _ref.completeProfileOnLogin,
47
51
  completeProfileOnLogin = _ref$completeProfileO === void 0 ? false : _ref$completeProfileO,
48
52
  _ref$requireTerms = _ref.requireTerms,
@@ -871,13 +875,18 @@ var PowrLogin = function PowrLogin(_ref) {
871
875
  style: styles.checkbox
872
876
  }), /*#__PURE__*/_react["default"].createElement("span", {
873
877
  style: styles.checkboxText
874
- }, "Remember me")), showForgotPassword && /*#__PURE__*/_react["default"].createElement("button", {
878
+ }, "Remember me")), passwordResetHelpUrl ? /*#__PURE__*/_react["default"].createElement("a", {
879
+ href: passwordResetHelpUrl,
880
+ target: "_blank",
881
+ rel: "noopener noreferrer",
882
+ style: styles.forgotPasswordLink
883
+ }, passwordResetHelpLabel) : showForgotPassword ? /*#__PURE__*/_react["default"].createElement("button", {
875
884
  type: "button",
876
885
  onClick: function onClick() {
877
886
  return setShowOtpOption(!showOtpOption);
878
887
  },
879
888
  style: styles.forgotPasswordLink
880
- }, "Forgot password?")), isLogin && showForgotPassword && showOtpOption && /*#__PURE__*/_react["default"].createElement("div", {
889
+ }, "Forgot password?") : null), isLogin && !passwordResetHelpUrl && showForgotPassword && showOtpOption && /*#__PURE__*/_react["default"].createElement("div", {
881
890
  style: styles.otpSection
882
891
  }, /*#__PURE__*/_react["default"].createElement("p", {
883
892
  style: styles.otpText
@@ -0,0 +1,468 @@
1
+ "use strict";
2
+
3
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ Object.defineProperty(exports, "POWR_IMPERSONATOR_KEY", {
8
+ enumerable: true,
9
+ get: function get() {
10
+ return _storage.POWR_IMPERSONATOR_KEY;
11
+ }
12
+ });
13
+ exports.PowrImpersonationBar = PowrImpersonationBar;
14
+ exports.PowrLoginAsDialog = PowrLoginAsDialog;
15
+ exports.canStartLoginAs = canStartLoginAs;
16
+ Object.defineProperty(exports, "clearImpersonator", {
17
+ enumerable: true,
18
+ get: function get() {
19
+ return _storage.clearImpersonator;
20
+ }
21
+ });
22
+ exports.enterLoginAs = enterLoginAs;
23
+ exports.exitLoginAs = exitLoginAs;
24
+ exports.notifyImpersonationExit = notifyImpersonationExit;
25
+ Object.defineProperty(exports, "readImpersonator", {
26
+ enumerable: true,
27
+ get: function get() {
28
+ return _storage.readImpersonator;
29
+ }
30
+ });
31
+ Object.defineProperty(exports, "viewAsLabel", {
32
+ enumerable: true,
33
+ get: function get() {
34
+ return _storage.viewAsLabel;
35
+ }
36
+ });
37
+ var _react = _interopRequireWildcard(require("react"));
38
+ var _auth = require("../utils/auth");
39
+ var _session = require("../session");
40
+ var _styles = require("../shell/styles");
41
+ var _storage = require("./storage");
42
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t3 in e) "default" !== _t3 && {}.hasOwnProperty.call(e, _t3) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t3)) && (i.get || i.set) ? o(f, _t3, i) : f[_t3] = e[_t3]); return f; })(e, t); }
43
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
44
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
45
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
46
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
47
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
48
+ function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
49
+ function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
50
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
51
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
52
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
53
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
54
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
55
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
56
+ function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
57
+ function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
58
+ function emitImpersonation() {
59
+ if (typeof window === "undefined") return;
60
+ window.dispatchEvent(new Event("powr-impersonation"));
61
+ }
62
+ function applyLiveSession(session, next) {
63
+ var _session$setSession;
64
+ (0, _session.writeStoredSession)(next);
65
+ session === null || session === void 0 || (_session$setSession = session.setSession) === null || _session$setSession === void 0 || _session$setSession.call(session, next.user, next.token, next.refreshToken || null);
66
+ emitImpersonation();
67
+ }
68
+ function adminSnapshot(session) {
69
+ var saved = (0, _storage.readImpersonator)();
70
+ if (saved !== null && saved !== void 0 && saved.token) return saved;
71
+ var stored = (0, _session.readStoredSession)();
72
+ return {
73
+ user: session !== null && session !== void 0 && session.token ? session.user : (stored === null || stored === void 0 ? void 0 : stored.user) || null,
74
+ token: (session === null || session === void 0 ? void 0 : session.token) || (stored === null || stored === void 0 ? void 0 : stored.token) || null,
75
+ refreshToken: session !== null && session !== void 0 && session.token ? session.refreshToken || null : (stored === null || stored === void 0 ? void 0 : stored.refreshToken) || null
76
+ };
77
+ }
78
+
79
+ /**
80
+ * Start or hop. The saved admin snapshot stays the original admin.
81
+ * Sends the admin token, not the account currently on screen.
82
+ */
83
+ function enterLoginAs(_x) {
84
+ return _enterLoginAs.apply(this, arguments);
85
+ }
86
+ /** Host audit, then restore the admin session. Throws if the audit does not land. */
87
+ function _enterLoginAs() {
88
+ _enterLoginAs = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(_ref) {
89
+ var _readImpersonator3;
90
+ var session, apiUrl, projectId, phoneOrEmail, admin, _yield$apiCall, ok, data;
91
+ return _regenerator().w(function (_context3) {
92
+ while (1) switch (_context3.n) {
93
+ case 0:
94
+ session = _ref.session, apiUrl = _ref.apiUrl, projectId = _ref.projectId, phoneOrEmail = _ref.phoneOrEmail;
95
+ admin = adminSnapshot(session);
96
+ if (admin.token) {
97
+ _context3.n = 1;
98
+ break;
99
+ }
100
+ throw new Error("Sign in as an admin first.");
101
+ case 1:
102
+ _context3.n = 2;
103
+ return (0, _auth.apiCall)(apiUrl, "/auth/impersonate", projectId, {
104
+ method: "POST",
105
+ headers: {
106
+ Authorization: "Bearer ".concat(admin.token)
107
+ },
108
+ body: {
109
+ phoneOrEmail: String(phoneOrEmail || "").trim()
110
+ }
111
+ });
112
+ case 2:
113
+ _yield$apiCall = _context3.v;
114
+ ok = _yield$apiCall.ok;
115
+ data = _yield$apiCall.data;
116
+ if (!(!ok || !(data !== null && data !== void 0 && data.token))) {
117
+ _context3.n = 3;
118
+ break;
119
+ }
120
+ throw new Error((data === null || data === void 0 ? void 0 : data.message) || "Could not open that account.");
121
+ case 3:
122
+ if (!((_readImpersonator3 = (0, _storage.readImpersonator)()) !== null && _readImpersonator3 !== void 0 && _readImpersonator3.token)) {
123
+ (0, _storage.writeImpersonator)(admin);
124
+ }
125
+ applyLiveSession(session, {
126
+ user: data.user,
127
+ token: data.token,
128
+ refreshToken: null
129
+ });
130
+ return _context3.a(2, data);
131
+ }
132
+ }, _callee3);
133
+ }));
134
+ return _enterLoginAs.apply(this, arguments);
135
+ }
136
+ function exitLoginAs(_x2) {
137
+ return _exitLoginAs.apply(this, arguments);
138
+ }
139
+ /**
140
+ * Best-effort exit audit. Reads the bearer before the caller clears storage.
141
+ * Sign out uses this so the host still records the leave.
142
+ */
143
+ function _exitLoginAs() {
144
+ _exitLoginAs = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(_ref2) {
145
+ var session, apiUrl, projectId, admin, _yield$apiCall2, ok, data;
146
+ return _regenerator().w(function (_context4) {
147
+ while (1) switch (_context4.n) {
148
+ case 0:
149
+ session = _ref2.session, apiUrl = _ref2.apiUrl, projectId = _ref2.projectId;
150
+ admin = (0, _storage.readImpersonator)();
151
+ if (admin !== null && admin !== void 0 && admin.token) {
152
+ _context4.n = 1;
153
+ break;
154
+ }
155
+ return _context4.a(2);
156
+ case 1:
157
+ _context4.n = 2;
158
+ return (0, _auth.apiCall)(apiUrl, "/auth/impersonate/exit", projectId, {
159
+ method: "POST",
160
+ body: {}
161
+ });
162
+ case 2:
163
+ _yield$apiCall2 = _context4.v;
164
+ ok = _yield$apiCall2.ok;
165
+ data = _yield$apiCall2.data;
166
+ if (ok) {
167
+ _context4.n = 3;
168
+ break;
169
+ }
170
+ throw new Error((data === null || data === void 0 ? void 0 : data.message) || "Could not leave this account.");
171
+ case 3:
172
+ (0, _storage.clearImpersonator)();
173
+ applyLiveSession(session, {
174
+ user: admin.user,
175
+ token: admin.token,
176
+ refreshToken: admin.refreshToken || null
177
+ });
178
+ case 4:
179
+ return _context4.a(2);
180
+ }
181
+ }, _callee4);
182
+ }));
183
+ return _exitLoginAs.apply(this, arguments);
184
+ }
185
+ function notifyImpersonationExit(_ref3) {
186
+ var _readImpersonator;
187
+ var apiUrl = _ref3.apiUrl,
188
+ projectId = _ref3.projectId;
189
+ if (!((_readImpersonator = (0, _storage.readImpersonator)()) !== null && _readImpersonator !== void 0 && _readImpersonator.token)) return Promise.resolve({
190
+ ok: true,
191
+ skipped: true
192
+ });
193
+ var token = (0, _auth.getAuthToken)();
194
+ if (!token) return Promise.resolve({
195
+ ok: true,
196
+ skipped: true
197
+ });
198
+ return (0, _auth.apiCall)(apiUrl, "/auth/impersonate/exit", projectId, {
199
+ method: "POST",
200
+ headers: {
201
+ Authorization: "Bearer ".concat(token)
202
+ },
203
+ body: {}
204
+ });
205
+ }
206
+ function PowrLoginAsDialog(_ref4) {
207
+ var open = _ref4.open,
208
+ onClose = _ref4.onClose,
209
+ apiUrl = _ref4.apiUrl,
210
+ projectId = _ref4.projectId,
211
+ onStarted = _ref4.onStarted;
212
+ var session = (0, _session.usePowrSession)();
213
+ var _useState = (0, _react.useState)(""),
214
+ _useState2 = _slicedToArray(_useState, 2),
215
+ value = _useState2[0],
216
+ setValue = _useState2[1];
217
+ var _useState3 = (0, _react.useState)(""),
218
+ _useState4 = _slicedToArray(_useState3, 2),
219
+ error = _useState4[0],
220
+ setError = _useState4[1];
221
+ var _useState5 = (0, _react.useState)(false),
222
+ _useState6 = _slicedToArray(_useState5, 2),
223
+ busy = _useState6[0],
224
+ setBusy = _useState6[1];
225
+ if (!open) return null;
226
+ var submit = /*#__PURE__*/function () {
227
+ var _ref5 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(event) {
228
+ var phoneOrEmail, _t;
229
+ return _regenerator().w(function (_context) {
230
+ while (1) switch (_context.p = _context.n) {
231
+ case 0:
232
+ event.preventDefault();
233
+ phoneOrEmail = value.trim();
234
+ if (phoneOrEmail) {
235
+ _context.n = 1;
236
+ break;
237
+ }
238
+ setError("Enter a phone number or email.");
239
+ return _context.a(2);
240
+ case 1:
241
+ setBusy(true);
242
+ setError("");
243
+ _context.p = 2;
244
+ _context.n = 3;
245
+ return enterLoginAs({
246
+ session: session,
247
+ apiUrl: apiUrl,
248
+ projectId: projectId,
249
+ phoneOrEmail: phoneOrEmail
250
+ });
251
+ case 3:
252
+ setValue("");
253
+ onStarted === null || onStarted === void 0 || onStarted();
254
+ onClose === null || onClose === void 0 || onClose();
255
+ _context.n = 5;
256
+ break;
257
+ case 4:
258
+ _context.p = 4;
259
+ _t = _context.v;
260
+ setError((_t === null || _t === void 0 ? void 0 : _t.message) || "Could not open that account.");
261
+ case 5:
262
+ _context.p = 5;
263
+ setBusy(false);
264
+ return _context.f(5);
265
+ case 6:
266
+ return _context.a(2);
267
+ }
268
+ }, _callee, null, [[2, 4, 5, 6]]);
269
+ }));
270
+ return function submit(_x3) {
271
+ return _ref5.apply(this, arguments);
272
+ };
273
+ }();
274
+ return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("div", {
275
+ style: _styles.s.overlay,
276
+ onClick: busy ? undefined : onClose,
277
+ "aria-hidden": true
278
+ }), /*#__PURE__*/_react["default"].createElement("div", {
279
+ role: "dialog",
280
+ "aria-modal": "true",
281
+ "aria-labelledby": "powr-login-as-title",
282
+ style: {
283
+ position: "fixed",
284
+ zIndex: 70,
285
+ top: "20vh",
286
+ left: "50%",
287
+ transform: "translateX(-50%)",
288
+ width: "min(400px, calc(100vw - 32px))",
289
+ padding: 16,
290
+ borderRadius: _styles.v.radius,
291
+ border: "1px solid ".concat(_styles.v.border),
292
+ background: _styles.v.surface,
293
+ color: _styles.v.text,
294
+ fontFamily: _styles.v.font,
295
+ boxShadow: "0 10px 30px rgba(0,0,0,0.12)"
296
+ }
297
+ }, /*#__PURE__*/_react["default"].createElement("form", {
298
+ onSubmit: submit
299
+ }, /*#__PURE__*/_react["default"].createElement("div", {
300
+ id: "powr-login-as-title",
301
+ style: {
302
+ fontWeight: 600,
303
+ fontSize: 16,
304
+ marginBottom: 8
305
+ }
306
+ }, "Login as"), /*#__PURE__*/_react["default"].createElement("p", {
307
+ style: {
308
+ margin: "0 0 12px",
309
+ fontSize: 13,
310
+ color: _styles.v.muted
311
+ }
312
+ }, "Phone or email of an account on this app. Their password stays as it is."), /*#__PURE__*/_react["default"].createElement("input", {
313
+ autoFocus: true,
314
+ value: value,
315
+ onChange: function onChange(e) {
316
+ return setValue(e.target.value);
317
+ },
318
+ placeholder: "Phone or email",
319
+ autoComplete: "off",
320
+ style: {
321
+ width: "100%",
322
+ boxSizing: "border-box",
323
+ height: 40,
324
+ padding: "0 10px",
325
+ borderRadius: _styles.v.radius,
326
+ border: "1px solid ".concat(_styles.v.border),
327
+ background: _styles.v.bg,
328
+ color: _styles.v.text,
329
+ fontSize: 14
330
+ }
331
+ }), error ? /*#__PURE__*/_react["default"].createElement("div", {
332
+ style: {
333
+ marginTop: 8,
334
+ fontSize: 13,
335
+ color: _styles.v.danger
336
+ }
337
+ }, error) : null, /*#__PURE__*/_react["default"].createElement("div", {
338
+ style: {
339
+ display: "flex",
340
+ justifyContent: "flex-end",
341
+ gap: 8,
342
+ marginTop: 14
343
+ }
344
+ }, /*#__PURE__*/_react["default"].createElement("button", {
345
+ type: "button",
346
+ onClick: onClose,
347
+ disabled: busy,
348
+ style: _styles.s.menuItem(false)
349
+ }, "Cancel"), /*#__PURE__*/_react["default"].createElement("button", {
350
+ type: "submit",
351
+ disabled: busy,
352
+ style: _objectSpread(_objectSpread({}, _styles.s.menuItem(false)), {}, {
353
+ width: "auto",
354
+ background: _styles.v.primary,
355
+ color: _styles.v.primaryFg,
356
+ borderRadius: _styles.v.radius,
357
+ padding: "8px 12px"
358
+ })
359
+ }, busy ? "Opening…" : "View account")))));
360
+ }
361
+
362
+ /** Banner while an admin is viewing someone else. Exit restores the admin session. */
363
+ function PowrImpersonationBar(_ref6) {
364
+ var apiUrl = _ref6.apiUrl,
365
+ projectId = _ref6.projectId;
366
+ var session = (0, _session.usePowrSession)();
367
+ var _useState7 = (0, _react.useState)(0),
368
+ _useState8 = _slicedToArray(_useState7, 2),
369
+ tick = _useState8[0],
370
+ setTick = _useState8[1];
371
+ var _useState9 = (0, _react.useState)(""),
372
+ _useState0 = _slicedToArray(_useState9, 2),
373
+ error = _useState0[0],
374
+ setError = _useState0[1];
375
+ var _useState1 = (0, _react.useState)(false),
376
+ _useState10 = _slicedToArray(_useState1, 2),
377
+ busy = _useState10[0],
378
+ setBusy = _useState10[1];
379
+ (0, _react.useEffect)(function () {
380
+ var refresh = function refresh() {
381
+ return setTick(function (n) {
382
+ return n + 1;
383
+ });
384
+ };
385
+ window.addEventListener("powr-impersonation", refresh);
386
+ window.addEventListener("storage", refresh);
387
+ return function () {
388
+ window.removeEventListener("powr-impersonation", refresh);
389
+ window.removeEventListener("storage", refresh);
390
+ };
391
+ }, []);
392
+ var snapshot = (0, _storage.readImpersonator)();
393
+ var stored = (0, _session.readStoredSession)();
394
+ var liveToken = session.token || (stored === null || stored === void 0 ? void 0 : stored.token);
395
+ var liveUser = session.token ? session.user : stored === null || stored === void 0 ? void 0 : stored.user;
396
+ if (!(snapshot !== null && snapshot !== void 0 && snapshot.token) || !liveToken) return null;
397
+ var leave = /*#__PURE__*/function () {
398
+ var _ref7 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
399
+ var _t2;
400
+ return _regenerator().w(function (_context2) {
401
+ while (1) switch (_context2.p = _context2.n) {
402
+ case 0:
403
+ setBusy(true);
404
+ setError("");
405
+ _context2.p = 1;
406
+ _context2.n = 2;
407
+ return exitLoginAs({
408
+ session: session,
409
+ apiUrl: apiUrl,
410
+ projectId: projectId
411
+ });
412
+ case 2:
413
+ _context2.n = 4;
414
+ break;
415
+ case 3:
416
+ _context2.p = 3;
417
+ _t2 = _context2.v;
418
+ setError((_t2 === null || _t2 === void 0 ? void 0 : _t2.message) || "Could not leave this account.");
419
+ case 4:
420
+ _context2.p = 4;
421
+ setBusy(false);
422
+ return _context2.f(4);
423
+ case 5:
424
+ return _context2.a(2);
425
+ }
426
+ }, _callee2, null, [[1, 3, 4, 5]]);
427
+ }));
428
+ return function leave() {
429
+ return _ref7.apply(this, arguments);
430
+ };
431
+ }();
432
+ return /*#__PURE__*/_react["default"].createElement("div", {
433
+ role: "status",
434
+ "data-rev": tick,
435
+ style: {
436
+ display: "flex",
437
+ alignItems: "center",
438
+ gap: 12,
439
+ minHeight: 36,
440
+ padding: "6px 16px",
441
+ background: _styles.v.primary,
442
+ color: _styles.v.primaryFg,
443
+ fontSize: 13,
444
+ fontFamily: _styles.v.font
445
+ }
446
+ }, /*#__PURE__*/_react["default"].createElement("span", {
447
+ style: {
448
+ flex: 1
449
+ }
450
+ }, "Viewing as ", (0, _storage.viewAsLabel)(liveUser), error ? " \u2014 ".concat(error) : ""), /*#__PURE__*/_react["default"].createElement("button", {
451
+ type: "button",
452
+ onClick: leave,
453
+ disabled: busy,
454
+ style: {
455
+ border: "1px solid ".concat(_styles.v.primaryFg),
456
+ background: "transparent",
457
+ color: _styles.v.primaryFg,
458
+ borderRadius: _styles.v.radius,
459
+ padding: "4px 10px",
460
+ cursor: busy ? "wait" : "pointer",
461
+ fontSize: 13
462
+ }
463
+ }, busy ? "Leaving…" : "Exit"));
464
+ }
465
+ function canStartLoginAs(session) {
466
+ var _readImpersonator2;
467
+ return Boolean((session === null || session === void 0 ? void 0 : session.isPowrAdmin) || ((_readImpersonator2 = (0, _storage.readImpersonator)()) === null || _readImpersonator2 === void 0 ? void 0 : _readImpersonator2.token));
468
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.POWR_IMPERSONATOR_KEY = void 0;
7
+ exports.clearImpersonator = clearImpersonator;
8
+ exports.readImpersonator = readImpersonator;
9
+ exports.viewAsLabel = viewAsLabel;
10
+ exports.writeImpersonator = writeImpersonator;
11
+ /** Admin session kept while Login As is active. Separate from `auth-store`. */
12
+ var POWR_IMPERSONATOR_KEY = exports.POWR_IMPERSONATOR_KEY = "powr-impersonator";
13
+ function readImpersonator() {
14
+ if (typeof window === "undefined") return null;
15
+ try {
16
+ var raw = window.localStorage.getItem(POWR_IMPERSONATOR_KEY);
17
+ if (!raw) return null;
18
+ var parsed = JSON.parse(raw);
19
+ if (!(parsed !== null && parsed !== void 0 && parsed.token)) return null;
20
+ return {
21
+ user: parsed.user || null,
22
+ token: parsed.token,
23
+ refreshToken: parsed.refreshToken || null
24
+ };
25
+ } catch (_unused) {
26
+ return null;
27
+ }
28
+ }
29
+ function writeImpersonator(snapshot) {
30
+ if (typeof window === "undefined" || !(snapshot !== null && snapshot !== void 0 && snapshot.token)) return;
31
+ window.localStorage.setItem(POWR_IMPERSONATOR_KEY, JSON.stringify({
32
+ user: snapshot.user || null,
33
+ token: snapshot.token,
34
+ refreshToken: snapshot.refreshToken || null
35
+ }));
36
+ }
37
+ function clearImpersonator() {
38
+ if (typeof window === "undefined") return;
39
+ window.localStorage.removeItem(POWR_IMPERSONATOR_KEY);
40
+ }
41
+ function viewAsLabel(user) {
42
+ return (user === null || user === void 0 ? void 0 : user.phoneNumber) || (user === null || user === void 0 ? void 0 : user.email) || (user === null || user === void 0 ? void 0 : user.fullName) || "this account";
43
+ }
package/dist/index.js CHANGED
@@ -76,6 +76,12 @@ Object.defineProperty(exports, "POWR_DENSITIES", {
76
76
  return _theme.POWR_DENSITIES;
77
77
  }
78
78
  });
79
+ Object.defineProperty(exports, "POWR_IMPERSONATOR_KEY", {
80
+ enumerable: true,
81
+ get: function get() {
82
+ return _impersonate.POWR_IMPERSONATOR_KEY;
83
+ }
84
+ });
79
85
  Object.defineProperty(exports, "POWR_SCHEMES", {
80
86
  enumerable: true,
81
87
  get: function get() {
@@ -244,6 +250,18 @@ Object.defineProperty(exports, "PowrCalendarStrip", {
244
250
  return _calendar["default"];
245
251
  }
246
252
  });
253
+ Object.defineProperty(exports, "PowrImpersonationBar", {
254
+ enumerable: true,
255
+ get: function get() {
256
+ return _impersonate.PowrImpersonationBar;
257
+ }
258
+ });
259
+ Object.defineProperty(exports, "PowrLoginAsDialog", {
260
+ enumerable: true,
261
+ get: function get() {
262
+ return _impersonate.PowrLoginAsDialog;
263
+ }
264
+ });
247
265
  Object.defineProperty(exports, "PowrOnboardingProvider", {
248
266
  enumerable: true,
249
267
  get: function get() {
@@ -304,6 +322,18 @@ Object.defineProperty(exports, "buildPowrSsoUrl", {
304
322
  return _sso.buildPowrSsoUrl;
305
323
  }
306
324
  });
325
+ Object.defineProperty(exports, "canStartLoginAs", {
326
+ enumerable: true,
327
+ get: function get() {
328
+ return _impersonate.canStartLoginAs;
329
+ }
330
+ });
331
+ Object.defineProperty(exports, "clearImpersonator", {
332
+ enumerable: true,
333
+ get: function get() {
334
+ return _impersonate.clearImpersonator;
335
+ }
336
+ });
307
337
  Object.defineProperty(exports, "clearStoredSession", {
308
338
  enumerable: true,
309
339
  get: function get() {
@@ -328,12 +358,24 @@ Object.defineProperty(exports, "defineOptionalAppStep", {
328
358
  return _onboarding.defineOptionalAppStep;
329
359
  }
330
360
  });
361
+ Object.defineProperty(exports, "enterLoginAs", {
362
+ enumerable: true,
363
+ get: function get() {
364
+ return _impersonate.enterLoginAs;
365
+ }
366
+ });
331
367
  Object.defineProperty(exports, "evaluateSteps", {
332
368
  enumerable: true,
333
369
  get: function get() {
334
370
  return _onboarding.evaluateSteps;
335
371
  }
336
372
  });
373
+ Object.defineProperty(exports, "exitLoginAs", {
374
+ enumerable: true,
375
+ get: function get() {
376
+ return _impersonate.exitLoginAs;
377
+ }
378
+ });
337
379
  Object.defineProperty(exports, "fetchThemePreference", {
338
380
  enumerable: true,
339
381
  get: function get() {
@@ -496,6 +538,12 @@ Object.defineProperty(exports, "profileNameStep", {
496
538
  return _onboarding.profileNameStep;
497
539
  }
498
540
  });
541
+ Object.defineProperty(exports, "readImpersonator", {
542
+ enumerable: true,
543
+ get: function get() {
544
+ return _impersonate.readImpersonator;
545
+ }
546
+ });
499
547
  Object.defineProperty(exports, "readStoredSession", {
500
548
  enumerable: true,
501
549
  get: function get() {
@@ -556,6 +604,12 @@ Object.defineProperty(exports, "usePowrThemeHost", {
556
604
  return _theme.usePowrThemeHost;
557
605
  }
558
606
  });
607
+ Object.defineProperty(exports, "viewAsLabel", {
608
+ enumerable: true,
609
+ get: function get() {
610
+ return _impersonate.viewAsLabel;
611
+ }
612
+ });
559
613
  Object.defineProperty(exports, "writeStoredSession", {
560
614
  enumerable: true,
561
615
  get: function get() {
@@ -591,5 +645,6 @@ var _sessionMessages = require("./utils/sessionMessages");
591
645
  var _theme = require("./theme");
592
646
  var _session = require("./session");
593
647
  var _shell = require("./shell");
648
+ var _impersonate = require("./impersonate");
594
649
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
595
650
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
@@ -16,6 +16,7 @@ exports.usePowrSession = usePowrSession;
16
16
  exports.writeStoredSession = writeStoredSession;
17
17
  var _react = _interopRequireWildcard(require("react"));
18
18
  var _jwt = require("../utils/jwt");
19
+ var _storage = require("../impersonate/storage");
19
20
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
20
21
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
21
22
  function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
@@ -183,6 +184,7 @@ function PowrSessionProvider(_ref2) {
183
184
  }, [controlled, persist]);
184
185
  var clear = (0, _react.useCallback)(function () {
185
186
  var _onChangeRef$current2;
187
+ (0, _storage.clearImpersonator)();
186
188
  if (!controlled) {
187
189
  setLocal(EMPTY);
188
190
  clearStoredSession();
@@ -16,6 +16,7 @@ var _PowrOnboardingProvider = _interopRequireDefault(require("../onboarding/Powr
16
16
  var _useMediaQuery = _interopRequireDefault(require("../utils/useMediaQuery"));
17
17
  var _styles = require("./styles");
18
18
  var _parts = require("./parts");
19
+ var _impersonate = require("../impersonate");
19
20
  var _excluded = ["theme", "presets", "scheme", "density", "preset", "persistTheme", "user", "token", "refreshToken", "onSessionChange", "onLogout"];
20
21
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
21
22
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
@@ -82,6 +83,7 @@ function PowrBaseAppWrapper(props) {
82
83
  }, shell);
83
84
  }
84
85
  function Shell(_ref) {
86
+ var _readImpersonator;
85
87
  var _ref$mode = _ref.mode,
86
88
  mode = _ref$mode === void 0 ? "topbar" : _ref$mode,
87
89
  _ref$brand = _ref.brand,
@@ -136,6 +138,20 @@ function Shell(_ref) {
136
138
  _useState4 = _slicedToArray(_useState3, 2),
137
139
  settingsOpen = _useState4[0],
138
140
  setSettingsOpen = _useState4[1];
141
+ var _useState5 = (0, _react.useState)(false),
142
+ _useState6 = _slicedToArray(_useState5, 2),
143
+ loginAsOpen = _useState6[0],
144
+ setLoginAsOpen = _useState6[1];
145
+ var viewingAs = Boolean(((_readImpersonator = (0, _impersonate.readImpersonator)()) === null || _readImpersonator === void 0 ? void 0 : _readImpersonator.token) && session.token);
146
+ var chromeOffset = _styles.HEADER_HEIGHT + (viewingAs ? 36 : 0);
147
+ var leaveAndSignOut = (0, _react.useCallback)(function () {
148
+ var pending = (0, _impersonate.notifyImpersonationExit)({
149
+ apiUrl: apiUrl,
150
+ projectId: projectId
151
+ });
152
+ session.clear();
153
+ pending["catch"](function () {});
154
+ }, [apiUrl, projectId, session]);
139
155
  var closeNav = (0, _react.useCallback)(function () {
140
156
  return setNavOpen(false);
141
157
  }, []);
@@ -214,8 +230,20 @@ function Shell(_ref) {
214
230
  var showBurger = narrow && nav.length > 0;
215
231
  var content = /*#__PURE__*/_react["default"].createElement("div", {
216
232
  style: _styles.s.root
217
- }, /*#__PURE__*/_react["default"].createElement("header", {
218
- style: _styles.s.header
233
+ }, /*#__PURE__*/_react["default"].createElement("div", {
234
+ style: {
235
+ position: "sticky",
236
+ top: 0,
237
+ zIndex: 40
238
+ }
239
+ }, /*#__PURE__*/_react["default"].createElement(_impersonate.PowrImpersonationBar, {
240
+ apiUrl: apiUrl,
241
+ projectId: projectId
242
+ }), /*#__PURE__*/_react["default"].createElement("header", {
243
+ style: _objectSpread(_objectSpread({}, _styles.s.header), {}, {
244
+ position: "relative",
245
+ top: "auto"
246
+ })
219
247
  }, showBurger ? /*#__PURE__*/_react["default"].createElement("button", {
220
248
  type: "button",
221
249
  "aria-label": "Menu",
@@ -247,16 +275,22 @@ function Shell(_ref) {
247
275
  onOpenSettings: showThemeSettings ? function () {
248
276
  return setSettingsOpen(true);
249
277
  } : null,
250
- onLogout: session.clear
278
+ onLoginAs: (0, _impersonate.canStartLoginAs)(session) ? function () {
279
+ return setLoginAsOpen(true);
280
+ } : null,
281
+ onLogout: leaveAndSignOut
251
282
  }) : /*#__PURE__*/_react["default"].createElement(Link, {
252
283
  href: loginHref,
253
284
  style: _objectSpread(_objectSpread({}, _styles.s.navItem(false, false)), {}, {
254
285
  border: "1px solid ".concat(_styles.v.border)
255
286
  })
256
- }, "Sign in"))), /*#__PURE__*/_react["default"].createElement("div", {
287
+ }, "Sign in")))), /*#__PURE__*/_react["default"].createElement("div", {
257
288
  style: _styles.s.body
258
289
  }, vertical && nav.length ? /*#__PURE__*/_react["default"].createElement("aside", {
259
- style: _styles.s.sidebar
290
+ style: _objectSpread(_objectSpread({}, _styles.s.sidebar), {}, {
291
+ top: chromeOffset,
292
+ height: "calc(100vh - ".concat(chromeOffset, "px)")
293
+ })
260
294
  }, /*#__PURE__*/_react["default"].createElement(_parts.NavList, {
261
295
  items: nav,
262
296
  pathname: pathname,
@@ -281,6 +315,13 @@ function Shell(_ref) {
281
315
  open: settingsOpen,
282
316
  onClose: closeSettings,
283
317
  host: syncThemeWithHost && session.token ? themeHost : null
318
+ }), /*#__PURE__*/_react["default"].createElement(_impersonate.PowrLoginAsDialog, {
319
+ open: loginAsOpen,
320
+ onClose: function onClose() {
321
+ return setLoginAsOpen(false);
322
+ },
323
+ apiUrl: apiUrl,
324
+ projectId: projectId
284
325
  }));
285
326
  if (onboarding === false || !session.user) return content;
286
327
  return /*#__PURE__*/_react["default"].createElement(_PowrOnboardingProvider["default"], _extends({
@@ -99,6 +99,7 @@ function ProfileMenu(_ref3) {
99
99
  adminHref = _ref3.adminHref,
100
100
  Link = _ref3.Link,
101
101
  onOpenSettings = _ref3.onOpenSettings,
102
+ onLoginAs = _ref3.onLoginAs,
102
103
  onLogout = _ref3.onLogout,
103
104
  _ref3$extraItems = _ref3.extraItems,
104
105
  extraItems = _ref3$extraItems === void 0 ? [] : _ref3$extraItems;
@@ -171,7 +172,17 @@ function ProfileMenu(_ref3) {
171
172
  }, item.icon ? /*#__PURE__*/_react["default"].createElement("span", {
172
173
  "aria-hidden": true
173
174
  }, item.icon) : null, " ", item.label);
174
- }), onOpenSettings ? /*#__PURE__*/_react["default"].createElement("button", {
175
+ }), onLoginAs ? /*#__PURE__*/_react["default"].createElement("button", {
176
+ type: "button",
177
+ role: "menuitem",
178
+ onClick: function onClick() {
179
+ setOpen(false);
180
+ onLoginAs();
181
+ },
182
+ style: _styles.s.menuItem(false)
183
+ }, /*#__PURE__*/_react["default"].createElement("span", {
184
+ "aria-hidden": true
185
+ }, "\u21AA"), " Login as") : null, onOpenSettings ? /*#__PURE__*/_react["default"].createElement("button", {
175
186
  type: "button",
176
187
  role: "menuitem",
177
188
  onClick: function onClick() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "powr-sdk-web",
3
- "version": "6.2.0",
3
+ "version": "6.3.0",
4
4
  "main": "dist/index.js",
5
5
  "files": [
6
6
  "dist"