saasufy-components 10.1.1 → 10.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -2
- package/collection-adder-form.js +13 -1
- package/collection-adder.js +14 -1
- package/log-out.js +44 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -457,7 +457,7 @@ This component is a simplified version of the `collection-adder-form` component
|
|
|
457
457
|
- `autocapitalize`: Can be set to `off` to disable auto-capitalization of the first input character on mobile devices.
|
|
458
458
|
- `autocorrect`: Can be set to `off` to disable auto-correction of input on mobile devices.
|
|
459
459
|
- `show-field-errors`: If this attribute exists on the element, then granular error messages will be shown above each corresponding input element instead of a single form-level error message.
|
|
460
|
-
- `trim-spaces`: If this attribute exists on the element, then leading and trailing spaces will be trimmed from each input element's value before submitting the form.
|
|
460
|
+
- `trim-spaces`: If this attribute exists on the element, then leading and trailing spaces will be trimmed from each input element's value before submitting the form. It can optionally be set to a comma-separated list of field names such as `trim-spaces="name,brand"`; in this case, only the values of the listed fields will be trimmed and all others will be left as they are. If the attribute has no value, then all input values will be trimmed.
|
|
461
461
|
- `reset-status-on-submit`: If this attribute exists, then the current message and any field errors will be cleared as soon as the form is submitted, instead of when the outcome of the submit is known. By default, the previous status is kept on screen until the insert either succeeds or fails and is then replaced within a single frame; this avoids the form flickering (shrinking and then growing again) when the same error occurs on consecutive submits.
|
|
462
462
|
- `consumers`: This allows you to connect this `collection-adder` to other elements on your page. It should be used in conjunction with the `provider-template` attribute. The `consumers` attribute 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 output of the `collection-adder` component on submit. 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.
|
|
463
463
|
- `success-consumers`: Same as the `consumers` attribute but the target elements are only updated if insertion was a success.
|
|
@@ -498,7 +498,7 @@ This component is similar to the `collection-adder` component except that it req
|
|
|
498
498
|
- `computable-model-values`: If this attribute exists on the element, then the `model-values` attribute will be re-computed before the form is submitted; this may be useful if the `model-values` attribute contains expressions which need to be updated before submitting.
|
|
499
499
|
- `success-message`: A message to show the user if the resource has been successfully added to the collection after submitting the form.
|
|
500
500
|
- `show-field-errors`: If this attribute exists on the element, then granular error messages will be shown above each corresponding input element instead of a single form-level error message.
|
|
501
|
-
- `trim-spaces`: If this attribute exists on the element, then leading and trailing spaces will be trimmed from each input element's value before submitting the form.
|
|
501
|
+
- `trim-spaces`: If this attribute exists on the element, then leading and trailing spaces will be trimmed from each input element's value before submitting the form. It can optionally be set to a comma-separated list of input names such as `trim-spaces="name,brand"`; in this case, only the values of the listed inputs will be trimmed and all others will be left as they are. If the attribute has no value, then all input values will be trimmed.
|
|
502
502
|
- `auto-reset-hidden-inputs`: If this attribute exists, then `hidden` input elements which are inside the `collection-adder-form` will be cleared along with other input fields. By default, `hidden` input elements are not cleared when the form is reset.
|
|
503
503
|
- `reset-status-on-submit`: If this attribute exists, then the current message and any field errors will be cleared as soon as the form is submitted, instead of when the outcome of the submit is known. By default, the previous status is kept on screen until the insert either succeeds or fails and is then replaced within a single frame; this avoids the form flickering (shrinking and then growing again) when the same error occurs on consecutive submits.
|
|
504
504
|
- `disable-submit-on-enter-key`: If this attribute exists, then the form will not submit when the enter key is pressed.
|
|
@@ -936,6 +936,8 @@ The change in the location hash can then be detected by an `app-router` to switc
|
|
|
936
936
|
|
|
937
937
|
A component which can be placed inside a `socket-provider` to deauthenticate the socket (e.g. on click).
|
|
938
938
|
|
|
939
|
+
If the user logged in via an OAuth provider which supports RP-initiated log out (such as Keycloak), deauthenticating the socket does not end the session on the provider itself; the user would be logged straight back in without being asked for their credentials the next time they log in. To also end the provider session, specify the `logout-url` attribute and the component will redirect the user to that endpoint after deauthenticating the socket.
|
|
940
|
+
|
|
939
941
|
**Import**
|
|
940
942
|
|
|
941
943
|
```html
|
|
@@ -948,6 +950,27 @@ A component which can be placed inside a `socket-provider` to deauthenticate the
|
|
|
948
950
|
<log-out onclick="logOut()"><a href="javascript:void(0)">Log out</a></log-out>
|
|
949
951
|
```
|
|
950
952
|
|
|
953
|
+
Logging out of Keycloak as well as of the app:
|
|
954
|
+
|
|
955
|
+
```html
|
|
956
|
+
<log-out
|
|
957
|
+
onclick="logOut()"
|
|
958
|
+
provider="keycloak"
|
|
959
|
+
logout-url="https://auth.example.com/realms/myrealm/protocol/openid-connect/logout"
|
|
960
|
+
client-id="myclient"
|
|
961
|
+
post-logout-redirect-uri="https://myapp.com/index.html"
|
|
962
|
+
><a href="javascript:void(0)">Log out</a></log-out>
|
|
963
|
+
```
|
|
964
|
+
|
|
965
|
+
**Attributes**
|
|
966
|
+
|
|
967
|
+
- `logout-url`: The log out endpoint of the OAuth provider; for OpenID Connect providers this is the `end_session_endpoint`. If it is not specified, the component only deauthenticates the socket. The redirect is skipped if the user did not log in via an OAuth provider.
|
|
968
|
+
- `provider`: The name of the OAuth provider, as specified on the `Authentication` page of your Saasufy control panel. If it is set, the redirect only happens when the user logged in via that specific provider; this is useful when your app offers several different ways to log in.
|
|
969
|
+
- `client-id`: The client ID to pass to the provider as the `client_id` query parameter. OpenID Connect providers require either this or an ID token in order to log the user out without asking them to confirm.
|
|
970
|
+
- `post-logout-redirect-uri`: The URL to send the user back to once the provider has logged them out, passed as the `post_logout_redirect_uri` query parameter. It usually needs to be registered with the provider in advance. If it is not specified, the user is left on the provider's own logged out page.
|
|
971
|
+
|
|
972
|
+
If the auth token contains an ID token (which requires the `idTokenField` of the provider to be set on the `Authentication` page of your Saasufy control panel), it is passed to the provider as the `id_token_hint` query parameter. Providers such as Keycloak show a log out confirmation page when it is missing. Any of these query parameters which are already present in `logout-url` are left untouched.
|
|
973
|
+
|
|
951
974
|
### oauth-link
|
|
952
975
|
|
|
953
976
|
A link to initiate an OAuth flow to authenticate a user as part of log in. Can support a range of different OAuth providers.
|
package/collection-adder-form.js
CHANGED
|
@@ -59,7 +59,15 @@ class CollectionAdderForm extends SocketConsumer {
|
|
|
59
59
|
this.clearStatus();
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
// The trim-spaces attribute can either be empty (in which case spaces are
|
|
63
|
+
// trimmed from all input values) or it can hold a comma-separated list of
|
|
64
|
+
// input names to restrict trimming to those specific inputs.
|
|
62
65
|
let trimSpaces = this.hasAttribute('trim-spaces');
|
|
66
|
+
let trimSpacesInputNames = trimSpaces ?
|
|
67
|
+
(this.getAttribute('trim-spaces') || '')
|
|
68
|
+
.split(',')
|
|
69
|
+
.map(inputName => inputName.trim())
|
|
70
|
+
.filter(inputName => inputName) : [];
|
|
63
71
|
|
|
64
72
|
let inputElements = this.getAllInputElements();
|
|
65
73
|
let outputValue;
|
|
@@ -113,7 +121,11 @@ class CollectionAdderForm extends SocketConsumer {
|
|
|
113
121
|
value = input.value;
|
|
114
122
|
}
|
|
115
123
|
let sanitizedValue = Type(value);
|
|
116
|
-
|
|
124
|
+
let shouldTrimSpaces = trimSpaces && (
|
|
125
|
+
!trimSpacesInputNames.length ||
|
|
126
|
+
trimSpacesInputNames.includes(input.name)
|
|
127
|
+
);
|
|
128
|
+
if (shouldTrimSpaces && typeof sanitizedValue === 'string') {
|
|
117
129
|
sanitizedValue = sanitizedValue.trim();
|
|
118
130
|
}
|
|
119
131
|
return [ input.name, sanitizedValue ];
|
package/collection-adder.js
CHANGED
|
@@ -70,7 +70,16 @@ class CollectionAdder extends SocketConsumer {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
// The trim-spaces attribute can either be empty (in which case spaces are
|
|
74
|
+
// trimmed from all input values) or it can hold a comma-separated list of
|
|
75
|
+
// field names to restrict trimming to those specific inputs.
|
|
73
76
|
let trimSpaces = this.hasAttribute('trim-spaces');
|
|
77
|
+
let trimSpacesFieldNames = trimSpaces ?
|
|
78
|
+
(this.getAttribute('trim-spaces') || '')
|
|
79
|
+
.split(',')
|
|
80
|
+
.map(fieldName => fieldName.trim())
|
|
81
|
+
.filter(fieldName => fieldName) : [];
|
|
82
|
+
|
|
74
83
|
let outputValue;
|
|
75
84
|
|
|
76
85
|
let modelValues = this.getAttribute('model-values');
|
|
@@ -116,7 +125,11 @@ class CollectionAdder extends SocketConsumer {
|
|
|
116
125
|
value = input.value;
|
|
117
126
|
}
|
|
118
127
|
let sanitizedValue = Type(value);
|
|
119
|
-
|
|
128
|
+
let shouldTrimSpaces = trimSpaces && (
|
|
129
|
+
!trimSpacesFieldNames.length ||
|
|
130
|
+
trimSpacesFieldNames.includes(input.name)
|
|
131
|
+
);
|
|
132
|
+
if (shouldTrimSpaces && typeof sanitizedValue === 'string') {
|
|
120
133
|
sanitizedValue = sanitizedValue.trim();
|
|
121
134
|
}
|
|
122
135
|
return [ input.name, sanitizedValue ];
|
package/log-out.js
CHANGED
|
@@ -1,8 +1,50 @@
|
|
|
1
1
|
import { SocketConsumer } from './socket.js';
|
|
2
2
|
|
|
3
3
|
class LogOut extends SocketConsumer {
|
|
4
|
-
|
|
5
|
-
this.
|
|
4
|
+
getProviderLogOutURL(authToken) {
|
|
5
|
+
let logoutURL = this.getAttribute('logout-url');
|
|
6
|
+
if (!logoutURL) return null;
|
|
7
|
+
|
|
8
|
+
// RP-initiated log out only applies to sessions which were created via an OAuth provider.
|
|
9
|
+
let authSource = authToken && authToken.authSource;
|
|
10
|
+
if (!authSource) return null;
|
|
11
|
+
let provider = this.getAttribute('provider');
|
|
12
|
+
if (provider && provider !== authSource) return null;
|
|
13
|
+
|
|
14
|
+
let providerLogOutURL;
|
|
15
|
+
try {
|
|
16
|
+
providerLogOutURL = new URL(logoutURL, location.origin);
|
|
17
|
+
} catch (error) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
'The logout-url attribute of log-out was not a valid URL'
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let clientId = this.getAttribute('client-id');
|
|
24
|
+
let postLogoutRedirectURI = this.getAttribute('post-logout-redirect-uri');
|
|
25
|
+
let searchParams = providerLogOutURL.searchParams;
|
|
26
|
+
|
|
27
|
+
// Without an id_token_hint, the provider asks the user to confirm the log out.
|
|
28
|
+
if (authToken.idToken && !searchParams.has('id_token_hint')) {
|
|
29
|
+
searchParams.set('id_token_hint', authToken.idToken);
|
|
30
|
+
}
|
|
31
|
+
if (clientId && !searchParams.has('client_id')) {
|
|
32
|
+
searchParams.set('client_id', clientId);
|
|
33
|
+
}
|
|
34
|
+
if (postLogoutRedirectURI && !searchParams.has('post_logout_redirect_uri')) {
|
|
35
|
+
searchParams.set('post_logout_redirect_uri', postLogoutRedirectURI);
|
|
36
|
+
}
|
|
37
|
+
return providerLogOutURL.href;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async logOut() {
|
|
41
|
+
let socket = this.getSocket();
|
|
42
|
+
// The auth token must be read before the socket is deauthenticated.
|
|
43
|
+
let providerLogOutURL = this.getProviderLogOutURL(socket.authToken);
|
|
44
|
+
await socket.deauthenticate();
|
|
45
|
+
if (providerLogOutURL) {
|
|
46
|
+
location.href = providerLogOutURL;
|
|
47
|
+
}
|
|
6
48
|
}
|
|
7
49
|
}
|
|
8
50
|
|