Skip to content

Commit 5db6547

Browse files
authored
Merge pull request #325 from lyra/KJS-3329
fix(loadLibrary): fix loadLibrary domain validation
2 parents 42dcdcc + 07ce515 commit 5db6547

File tree

19 files changed

+1993
-195
lines changed

19 files changed

+1993
-195
lines changed

.github/workflows/tests.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
name: E2E Tests
1+
name: Tests
22
on:
33
push:
44
branches: [main, master]
55
pull_request:
66
branches: [main, master]
77
jobs:
8-
test:
8+
test-e2e:
99
timeout-minutes: 60
1010
runs-on: ubuntu-latest
1111
steps:
@@ -30,3 +30,15 @@ jobs:
3030
name: playwright-report
3131
path: playwright-report/
3232
retention-days: 30
33+
test-unit:
34+
timeout-minutes: 60
35+
runs-on: ubuntu-latest
36+
steps:
37+
- uses: actions/checkout@v3
38+
- uses: actions/setup-node@v3
39+
with:
40+
node-version: 18
41+
- name: Install dependencies
42+
run: npm ci
43+
- name: Run unit tests
44+
run: npm run test:unit

README.md

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!-- BACK TO TOP LINK -->
2-
<a id="readme-top"></a>
32

3+
<a id="readme-top"></a>
44

55
<!-- PROJECT SHIELDS -->
66
<div align="center">
@@ -37,21 +37,20 @@
3737
</p>
3838
</div>
3939

40-
4140
![SmartForm](./assets/smartform.png)
4241

4342
## About the project
4443

4544
Any payment form must comply with PCI-DSS requirements. A classical integration will be displayed
4645
on the banks page using a redirection. In that case, PCI-DSS requirements are done by your bank.
4746

48-
By using this package Lyra allows to integrate a payment form using standard HTML elements on your
49-
website. This library will load the [Javacript library][doc-home] from Lyra servers transforming
50-
automatically each sensitive field (pan, security code, ...) into an IFrame, allowing to comply with
47+
By using this package Lyra allows to integrate a payment form using standard HTML elements on your
48+
website. This library will load the [Javacript library][doc-home] from Lyra servers transforming
49+
automatically each sensitive field (pan, security code, ...) into an IFrame, allowing to comply with
5150
all regulations.
5251

53-
The **embedded-form-glue** library provides a set of utilities to easily integrate the Payment
54-
form into any we application made with Javascript frameworks like React, Vue, Angular, Svelte,
52+
The **embedded-form-glue** library provides a set of utilities to easily integrate the Payment
53+
form into any we application made with Javascript frameworks like React, Vue, Angular, Svelte,
5554
Ionic, etc.
5655

5756
## Getting Started
@@ -77,15 +76,17 @@ First, define the theme files to load in the head section of your HTML page:
7776
```html
7877
<head>
7978
(...)
80-
<link rel="stylesheet"
81-
href="~~CHANGE_ME_ENDPOINT~~/static/js/krypton-client/V4.0/ext/neon-reset.css">
79+
<link
80+
rel="stylesheet"
81+
href="~~CHANGE_ME_ENDPOINT~~/static/js/krypton-client/V4.0/ext/neon-reset.css"
82+
/>
8283
<script src="~~CHANGE_ME_ENDPOINT~~/static/js/krypton-client/V4.0/ext/neon.js"></script>
8384
(...)
8485
</head>
8586
```
8687

8788
> **Note**
88-
>
89+
>
8990
> Replace **`~~CHANGE_ME_ENDPOINT~~`** with your configuration endpoint.
9091
9192
For more information about theming, please see [Lyra theming documentation][doc-themes]
@@ -101,45 +102,44 @@ After that, define the location where the payment form will be generated in your
101102
```
102103

103104
> **Note**
104-
>
105-
> Specifify the element **kr-smart-form** inside the target location to load the Smart Form (any
105+
>
106+
> Specifify the element **kr-smart-form** inside the target location to load the Smart Form (any
106107
> kind of payment method).
107108
108109
### Javascript
109110

110111
Import the library in your javascript file or component with:
111112

112113
```javascript
113-
import KRGlue from "@lyracom/embedded-form-glue";
114+
import KRGlue from '@lyracom/embedded-form-glue'
114115
```
115116

116117
And finally, you can generate the payment form with the following code:
117118

118119
```javascript
119120
/* Integration public key */
120-
const publicKey = '~~CHANGE_ME_PUBLIC_KEY~~';
121-
/* Endpoint. Must include the protocol (https://) */
122-
const endPoint = '~~CHANGE_ME_ENDPOINT~~';
121+
const publicKey = '~~CHANGE_ME_PUBLIC_KEY~~'
122+
/* Endpoint. Base domain with its protocol (e.g. https://domain.name, do not include any path after the domain) */
123+
const endPoint = '~~CHANGE_ME_ENDPOINT~~'
123124

124125
/* Load the remote library and get the KR object */
125-
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
126+
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
126127
/* Setting configuration */
127128
await KR.setFormConfig({ 'kr-language': 'en-US' })
128-
/* Attach a payment form to a given DOM selector */
129-
const { result } = await KR.attachForm('#myPaymentForm')
130-
/* Show the payment form */
131-
await KR.showForm(result.formId);
129+
/* Render the payment form into a given DOM selector */
130+
await KR.renderElements('#myPaymentForm')
132131
```
132+
133133
> **Note**
134-
>
134+
>
135135
> Replace **`~~CHANGE_ME_PUBLIC_KEY~~`** with your configuration public key.
136-
>
136+
>
137137
> Replace **`~~CHANGE_ME_ENDPOINT~~`** with your configuration endpoint.
138138
139139
> **Warning**
140-
>
141-
> KR methods use Promises. You should always use the **await** keyword or **then method** when
142-
> calling them. Please see [Javascript Promises][js-promises] and [Async Functions][js-async-await]
140+
>
141+
> KR methods use Promises. You should always use the **await** keyword or **then method** when
142+
> calling them. Please see [Javascript Promises][js-promises] and [Async Functions][js-async-await]
143143
> for more information.
144144
145145
## First transaction
@@ -148,8 +148,8 @@ Once the payment form is set up, you will see the skeleton animation. This is be
148148
using the default demo token. To make a real transaction, you need to get a real **formToken**.
149149

150150
To get a proper test **formToken**, make a request to the Charge/CreatePayment web service. To not
151-
expose your credentials, it is mandatory to do that from a server. Please see the
152-
[NodeJS server example](examples/server/README.md), or visit the following links for more
151+
expose your credentials, it is mandatory to do that from a server. Please see the
152+
[NodeJS server example](examples/server/README.md), or visit the following links for more
153153
information:
154154

155155
- [Embedded form quick start][doc-quick-start]
@@ -160,10 +160,14 @@ Once you have a **formToken**, you can set it in the payment form with the follo
160160

161161
```javascript
162162
// Use the loadLibrary to set the form token
163-
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey, '~~CHANGE_ME_FORM_TOKEN~~')
163+
const { KR } = await KRGlue.loadLibrary(
164+
endPoint,
165+
publicKey,
166+
'~~CHANGE_ME_FORM_TOKEN~~'
167+
)
164168

165169
// Or set the form token once the library is loaded
166-
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
170+
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
167171
await KR.setFormConfig({ formToken: '~~CHANGE_ME_FORM_TOKEN~~' })
168172
```
169173

@@ -178,11 +182,11 @@ methods.
178182

179183
### loadLibrary
180184

181-
Use `loadLibrary` method to load the Lyra Javascript library. The method returns a `Promise` with
185+
Use `loadLibrary` method to load the Lyra Javascript library. The method returns a `Promise` with
182186
the `KR` object.
183187

184188
```javascript
185-
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
189+
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
186190
```
187191

188192
## KR object
@@ -195,7 +199,7 @@ The available methods and callbacks are described in the following sections.
195199
- [KR callbacks](./docs/kr_callbacks.md)
196200

197201
> **Note**
198-
>
202+
>
199203
> See Lyra [Javascript library reference][doc-reference] for the complete reference guide.
200204
201205
## JavaScript frameworks integration
@@ -221,14 +225,15 @@ The payment form can be customized in many ways. Some of them in the following e
221225
- [Add additional fields](./docs/customization#add-additional-fields)
222226
- [Use a different HTML structure](./docs/customization#use-a-different-html-structure)
223227

224-
Any of these customizations can be done using the same method **KR.attachForm()**.
228+
Any of these customizations can be done using the same method **KR.renderElements()**.
225229

226230
> **Note**
227-
>
228-
> Please see the [Field Customization][doc-customization] section of the documentation for more
231+
>
232+
> Please see the [Field Customization][doc-customization] section of the documentation for more
229233
> information.
230234
231235
<!-- CONTRIBUTING -->
236+
232237
## Contributing
233238

234239
Contributions are welcome and pull requests will be reviewed and taken into account.
@@ -260,17 +265,19 @@ npm run examples:serve
260265
Execute the tests with the command:
261266

262267
```bash
263-
npm run test
268+
npm run test:e2e
264269
```
265270

266271
<!-- LICENSE -->
272+
267273
## License
268274

269275
Distributed under the MIT License. See the [LICENSE file](./LICENCE.txt) for more information.
270276

271277
<p align="right">(<a href="#readme-top">back to top</a>)</p>
272278

273279
<!-- MARKDOWN LINKS & IMAGES -->
280+
274281
[build-shield]: https://img.shields.io/circleci/build/github/lyra/embedded-form-glue?style=for-the-badge&logo=github
275282
[build-url]: https://circleci.com/gh/lyra/embedded-form-glue
276283
[npm-shield]: https://img.shields.io/npm/v/@lyracom/embedded-form-glue?style=for-the-badge&logo=npm
@@ -285,6 +292,7 @@ Distributed under the MIT License. See the [LICENSE file](./LICENCE.txt) for mor
285292
[license-url]: https://github.com/lyra/embedded-form-glue/blob/master/LICENSE.txt
286293

287294
<!-- DOC LINKS -->
295+
288296
[doc-home]: https://docs.lyra.com/en/rest/V4.0/javascript/
289297
[doc-quick-start]: https://docs.lyra.com/en/rest/V4.0/javascript/quick_start_js.html
290298
[doc-reference]: https://docs.lyra.com/en/rest/V4.0/javascript/features/reference.html

app/KryptonGlue.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,23 @@ class Glue {
1919
}
2020

2121
loadLibrary(domain, publicKey, formToken = null) {
22-
const domainRegex =
23-
/^(?:http(s)?:\/\/)[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=.]+$/g
2422
const pubKeyRegex = /^\d{2,8}:(|test)publickey_.+$/g
2523

2624
if (this.loaded) return this.getKrypton(publicKey)
2725
if (!domain) return Promise.reject('Domain not defined')
2826
if (!publicKey) return Promise.reject('Public key not defined')
2927

30-
if (!domainRegex.test(domain)) {
28+
// Domain validation
29+
try {
30+
const domainUrl = new URL(domain)
31+
32+
if (!['http:', 'https:'].includes(domainUrl.protocol))
33+
throw new Error('Invalid protocol')
34+
35+
if (domainUrl.port) throw new Error('No port allowed')
36+
if (domainUrl.search !== '') throw new Error('No query params allowed')
37+
if (domainUrl.pathname !== '/') throw new Error('Invalid path')
38+
} catch (err) {
3139
console.error('Domain format should be https://domain.name')
3240
return Promise.reject(`[${domain}] is not a valid endpoint domain`)
3341
}

docs/customization.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ The payment form can be customized in many ways like:
1212
<div class="kr-pan"></div>
1313
<div class="kr-expiry"></div>
1414
</div>
15-
</div>
15+
</div>
1616
</div>
1717
```
1818

@@ -23,7 +23,7 @@ The payment form can be customized in many ways like:
2323
<div class="kr-smart-form">
2424
<div class="kr-embedded">
2525
<div class="kr-pan"></div>
26-
<input
26+
<input
2727
class="kr-theme my-custom-email-field"
2828
type="text"
2929
name="email"
@@ -57,13 +57,13 @@ The payment form can be customized in many ways like:
5757
</div>
5858
<div class="kr-expiry"></div>
5959
</div>
60-
</div>
60+
</div>
6161
</div>
6262
```
6363

64-
Any of these customizations can be done using the same method **KR.attachForm()**.
64+
Any of these customizations can be done using the same method **KR.renderElements()**.
6565

6666
> **Note**
67-
>
68-
> Please see the [Field Customization][doc-customization] section of the documentation for more
69-
> information.
67+
>
68+
> Please see the [Field Customization][doc-customization] section of the documentation for more
69+
> information.

docs/kr_methods.md

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
1-
21
# KR object methods
32

43
These are the current available methods to manipulate the payment form:
54

6-
## attachForm
5+
## renderElements
6+
7+
Render a payment form into a given DOM selector: return a `promise` with the `KR` object and result.
8+
9+
```javascript
10+
const selector = `#myPaymentForm` // DOM selector
11+
const { KR, result } = await KR.renderElements(selector)
12+
```
13+
14+
> **_NOTE:_** if nothing is provided renderElements will search the complete DOM for the supported HTML elements
15+
16+
## attachForm (DEPRECATED use renderElements instead)
717

818
Attach a payment form to a given DOM selector: return a `promise` with the `KR` object and result.
919

@@ -20,8 +30,9 @@ Add a payment form to a given DOM selector: return a `promise` with the `KR` obj
2030
const selector = `#myPaymentForm` // DOM selector
2131
const { KR, result } = await KR.addForm(selector)
2232
```
33+
2334
> **Warning**
24-
>
35+
>
2536
> Only for cards payment method
2637
2738
## showForm
@@ -42,7 +53,6 @@ const { result } = await KR.addForm(selector)
4253
const { KR } = await KR.hideForm(result.formId)
4354
```
4455

45-
4656
## setFormConfig
4757

4858
Set the configuration of the payment form on runtime: return a `promise` with the `KR` object.
@@ -53,8 +63,9 @@ const { KR } = await KR.setFormConfig({
5363
language: `en-US`
5464
})
5565
```
66+
5667
> **Note**
57-
>
68+
>
5869
> Please see the [type definition](../index.d.ts) file for the list of available configuration options.
5970
6071
## validateForm
@@ -87,7 +98,6 @@ available in the payment form.
8798
const { KR } = await KR.openPaymentMethod('cards')
8899
```
89100

90-
91101
## openPopin
92102

93103
On popin mode, open the payment form in a popin: return a `promise` with the `KR` object.
@@ -159,10 +169,11 @@ Remove all generated payment forms: return a `promise` with the `KR` object.
159169
```javascript
160170
const { KR } = await KR.removeForms()
161171
```
172+
162173
## removeEventCallbacks
163174

164175
Remove all event callbacks: return a `promise` with the `KR` object.
165176

166177
```javascript
167178
const { KR } = await KR.removeEventCallbacks()
168-
```
179+
```

0 commit comments

Comments
 (0)