saasufy-components 3.27.4 → 3.29.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 +7 -4
- package/input-transformer.js +3 -1
- package/oauth-handler.js +3 -2
- package/oauth-link.js +5 -3
- package/package.json +1 -1
- package/utils.js +10 -7
package/README.md
CHANGED
|
@@ -222,8 +222,8 @@ So for example, if your `index.html` file is served up from the URL `http://mywe
|
|
|
222
222
|
- `route-path`: The path of the page. Supports custom URL parameters in the format `/org/:orgId/user/:userId`.
|
|
223
223
|
- `partial-route`: An optional attribute which, if specified, will allow the `route-path` to be matched partially from the start. This can be used to ignore the ending of a path which is not relevant to the page in order to avoid unnecessary re-renders.
|
|
224
224
|
- `redirect`: An optional path/route which this page should redirect to. Note that the content of this page will not be shown so it should always be empty.
|
|
225
|
-
- `no-auth-redirect`: An optional alternative path/route to redirect to if the user
|
|
226
|
-
- `auth-redirect`: An optional alternative path/route to redirect to if the user
|
|
225
|
+
- `no-auth-redirect`: An optional alternative path/route to redirect to if the user is on this page but they are not authenticated. If the user is authenticated, then the content of the template will be displayed as normal.
|
|
226
|
+
- `auth-redirect`: An optional alternative path/route to redirect to if the user is on this page but they are already authenticated. If the user is not authenticated, then the content of the template will be displayed as normal.
|
|
227
227
|
- `hard-redirect`: An optional, additional attribute which can be specified alongside a `redirect`, `no-auth-redirect` or `auth-redirect` attribute to ensure that any redirect will change the URL in the address bar. Redirects are `soft` redirects by default; this means that they redirect the user to the target page but keep the current URL path unchanged.
|
|
228
228
|
|
|
229
229
|
### socket-provider
|
|
@@ -710,6 +710,7 @@ The following example shows how to bind an `input-provider` component to an `inp
|
|
|
710
710
|
|
|
711
711
|
- `consumers`: This allows you to connect this `input-transformer` to other elements on your page. It takes a list of selectors with optional attributes to target in the format `element-selector:attribute-name`. For example `.my-input:value` will find all elements with a `my-input` class and update their `value` attributes with the value of the `input-provider` component in real-time. You can specify multiple selectors separated by commas such as `.my-input,my-div`; in this case, because attribute names are not specified, values will be injected into the `value` attribute (for input elements) or into the `innerHTML` property (for other kinds of elements). The default attribute/property depends on the element type.
|
|
712
712
|
- `provider-template`: A template string within which the `{{value}}` can be injected before passing to consumers.
|
|
713
|
+
- `output-type`: The default output type is `string`. This property can be used to convert the output to either `boolean` or `number`.
|
|
713
714
|
- `debounce-delay`: The delay in milliseconds to wait before triggering a change event. This is useful to batch multiple updates together. Default is 0ms.
|
|
714
715
|
|
|
715
716
|
### log-in-form
|
|
@@ -792,7 +793,8 @@ A link to initiate an OAuth flow to authenticate a user as part of log in. Can s
|
|
|
792
793
|
- `provider` (required): The name of the provider. It must match the provider name specified on the `Authentication` page of your Saasufy control panel and also the value provided to the `oauth-handler` component at the end of the OAuth flow.
|
|
793
794
|
- `client-id` (required): This is the client ID from the third-party OAuth provider.
|
|
794
795
|
- `state-size`: This allows you to control the size (in bytes) of the random state string which is passed to the OAuth provider as part of the OAuth flow. Defaults to 20.
|
|
795
|
-
- `state-
|
|
796
|
+
- `state-storage-key`: The state string is stored in the browser's `sessionStorage` under this key. Defaults to `oauth.state`. It must match the value provided to the `oauth-handler` component at the end of the OAuth flow.
|
|
797
|
+
- `use-local-storage`: By default, the state is stored inside sessionStorage. If this property is set, then the state will be stored inside localStorage instead. This is useful for sharing the state across different tabs. If set, this attribute should also be set on the related `oauth-handler` component.
|
|
796
798
|
|
|
797
799
|
### oauth-handler
|
|
798
800
|
|
|
@@ -818,10 +820,11 @@ When using an OAuth provider, the callback URL which you register with the provi
|
|
|
818
820
|
- `success-url`: If authentication is successful, the browser's `location.href` will be set to this value. It can be used to redirect the user to their dashboard, for example.
|
|
819
821
|
- `extra-data`: This attribute can be used to pass additional data to the OAuth `getAccessTokenURL` endpoint. For Google OAuth, for example, an additional `redirect_uri` field is required, so it should be set using `extra-data="redirect_uri=http://localhost.com:8000/"` (substitute the URI with your own).
|
|
820
822
|
- `navigate-event-path`: If authentication is successful and a path is set via this attribute, the component will emit a `navigate` event which will bubble up the component hierarchy and can be used by a parent component to perform the success redirection. This approach can be used as an alternative to `success-location-hash` or `success-url` for doing the final redirect.
|
|
821
|
-
- `state-
|
|
823
|
+
- `state-storage-key`: The state string is stored in the browser's `sessionStorage` under this key. Defaults to `oauth.state`. It must match the value provided to the `oauth-link` component at the start of the OAuth flow.
|
|
822
824
|
- `code-param-name`: The name of the query parameter which holds the `code` as provided by the OAuth provider within the OAuth callback URL. Defaults to `code`.
|
|
823
825
|
- `state-param-name`: The name of the query parameter which holds the `state` as provided by the OAuth provider within the OAuth callback URL. Defaults to `state`.
|
|
824
826
|
- `auth-timeout`: The number of milliseconds to wait for authentication to complete before timing out. Defaults to 10000 (10 seconds).
|
|
827
|
+
- `use-local-storage`: By default, the state is retrieved from sessionStorage. If this property is set, then the state will be retrieved from localStorage instead. This is useful for sharing the state across different tabs. If set, this attribute should also be set on the related `oauth-link` component.
|
|
825
828
|
|
|
826
829
|
### render-group
|
|
827
830
|
|
package/input-transformer.js
CHANGED
|
@@ -18,6 +18,7 @@ class InputTransformer extends HTMLElement {
|
|
|
18
18
|
'consumers',
|
|
19
19
|
'debounce-delay',
|
|
20
20
|
'provider-template',
|
|
21
|
+
'output-type',
|
|
21
22
|
'value'
|
|
22
23
|
];
|
|
23
24
|
}
|
|
@@ -30,6 +31,7 @@ class InputTransformer extends HTMLElement {
|
|
|
30
31
|
if (!this.hasAttribute('value')) return;
|
|
31
32
|
|
|
32
33
|
let value = this.getAttribute('value') || '';
|
|
34
|
+
let outputType = this.getAttribute('output-type');
|
|
33
35
|
let debounceDelay = this.getAttribute('debounce-delay');
|
|
34
36
|
debounceDelay = debounceDelay ? Number(debounceDelay) : DEFAULT_DEBOUNCE_DELAY;
|
|
35
37
|
|
|
@@ -40,7 +42,7 @@ class InputTransformer extends HTMLElement {
|
|
|
40
42
|
|
|
41
43
|
this.debounce(async () => {
|
|
42
44
|
let providerTemplate = this.getAttribute('provider-template') || '{{value}}';
|
|
43
|
-
updateConsumerElements(consumers, value, providerTemplate);
|
|
45
|
+
updateConsumerElements(consumers, value, providerTemplate, null, outputType);
|
|
44
46
|
}, debounceDelay);
|
|
45
47
|
}
|
|
46
48
|
}
|
package/oauth-handler.js
CHANGED
|
@@ -33,8 +33,9 @@ class OAuthHandler extends SocketConsumer {
|
|
|
33
33
|
throw new Error('The provider attribute of oauth-handler was not specified');
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
let
|
|
37
|
-
let
|
|
36
|
+
let useLocalStorage = this.hasAttribute('use-local-storage');
|
|
37
|
+
let storageKey = this.getAttribute('state-storage-key') || 'oauth.state';
|
|
38
|
+
let expectedOAuthState = (useLocalStorage ? localStorage : sessionStorage).getItem(storageKey);
|
|
38
39
|
if (!expectedOAuthState) {
|
|
39
40
|
this.innerHTML = `
|
|
40
41
|
<div class="error">OAuth authentication failed because the state was missing.</div>
|
package/oauth-link.js
CHANGED
|
@@ -16,7 +16,8 @@ class OAuthLink extends HTMLElement {
|
|
|
16
16
|
'provider',
|
|
17
17
|
'client-id',
|
|
18
18
|
'state-size',
|
|
19
|
-
'state-
|
|
19
|
+
'state-storage-key',
|
|
20
|
+
'use-local-storage'
|
|
20
21
|
];
|
|
21
22
|
}
|
|
22
23
|
|
|
@@ -71,10 +72,11 @@ class OAuthLink extends HTMLElement {
|
|
|
71
72
|
if (!provider) {
|
|
72
73
|
throw new Error('The provider attribute of oauth-link was not specified');
|
|
73
74
|
}
|
|
75
|
+
let useLocalStorage = this.hasAttribute('use-local-storage');
|
|
74
76
|
let stateSize = Number(this.getAttribute('state-size') || 20);
|
|
75
|
-
let
|
|
77
|
+
let storageKey = this.getAttribute('state-storage-key') || 'oauth.state';
|
|
76
78
|
this.state = `${provider}-${generateRandomHexString(stateSize)}`;
|
|
77
|
-
sessionStorage.setItem(
|
|
79
|
+
(useLocalStorage ? localStorage : sessionStorage).setItem(storageKey, this.state);
|
|
78
80
|
|
|
79
81
|
this.shadowRoot.innerHTML = `
|
|
80
82
|
<slot name="item"></slot>
|
package/package.json
CHANGED
package/utils.js
CHANGED
|
@@ -233,7 +233,7 @@ let templateFormatters = {
|
|
|
233
233
|
computeId
|
|
234
234
|
};
|
|
235
235
|
|
|
236
|
-
let
|
|
236
|
+
let templateTripleTagsRegExp = /{{{.*?}}}/gs;
|
|
237
237
|
let templateTagsRegExp = /{{.*?}}/gs;
|
|
238
238
|
|
|
239
239
|
function execExpression(expression, options) {
|
|
@@ -264,7 +264,7 @@ function getRenderOptions(data, socket) {
|
|
|
264
264
|
|
|
265
265
|
export function renderTemplate(templateString, data, socket) {
|
|
266
266
|
return templateString
|
|
267
|
-
.replace(
|
|
267
|
+
.replace(templateTripleTagsRegExp, (match) => {
|
|
268
268
|
let expString = match.slice(3, -3);
|
|
269
269
|
let options = getRenderOptions(data, socket);
|
|
270
270
|
try {
|
|
@@ -292,7 +292,7 @@ export function renderTemplate(templateString, data, socket) {
|
|
|
292
292
|
});
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
-
export function updateConsumerElements(consumers, value, template, sourceElementName) {
|
|
295
|
+
export function updateConsumerElements(consumers, value, template, sourceElementName, outputType) {
|
|
296
296
|
if (consumers) {
|
|
297
297
|
let consumerParts = consumers.split(',')
|
|
298
298
|
.filter(part => part)
|
|
@@ -303,10 +303,13 @@ export function updateConsumerElements(consumers, value, template, sourceElement
|
|
|
303
303
|
.filter(([ selector, attributeName ]) => selector);
|
|
304
304
|
|
|
305
305
|
if (template) {
|
|
306
|
-
value = renderTemplate(
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
306
|
+
value = renderTemplate(template, { value });
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (outputType === 'boolean') {
|
|
310
|
+
value = value !== 'false' && value !== '';
|
|
311
|
+
} else if (outputType === 'number') {
|
|
312
|
+
value = Number(value);
|
|
310
313
|
}
|
|
311
314
|
|
|
312
315
|
for (let [ selector, attributeName ] of consumerParts) {
|