payload 0.20.8-beta.0 → 1.0.4
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/CHANGELOG.md +607 -852
- package/components/styles.css +1 -1
- package/dist/admin/components/elements/Banner/index.scss +1 -0
- package/dist/admin/components/elements/ColumnSelector/index.scss +4 -7
- package/dist/admin/components/elements/Eyebrow/index.scss +4 -0
- package/dist/admin/components/elements/Nav/index.js +2 -2
- package/dist/admin/components/elements/Pill/index.scss +1 -0
- package/dist/admin/components/elements/ReactSelect/index.js +2 -2
- package/dist/admin/components/elements/ReactSelect/types.d.ts +1 -0
- package/dist/admin/components/forms/field-types/Array/Array.js +1 -1
- package/dist/admin/components/forms/field-types/Blocks/Blocks.js +1 -1
- package/dist/admin/components/forms/field-types/Checkbox/index.js +1 -1
- package/dist/admin/components/forms/field-types/Code/Code.js +1 -1
- package/dist/admin/components/forms/field-types/DateTime/index.js +1 -1
- package/dist/admin/components/forms/field-types/Email/index.js +2 -2
- package/dist/admin/components/forms/field-types/Group/index.js +1 -1
- package/dist/admin/components/forms/field-types/HiddenInput/index.js +1 -1
- package/dist/admin/components/forms/field-types/Number/index.js +2 -2
- package/dist/admin/components/forms/field-types/Password/index.js +2 -2
- package/dist/admin/components/forms/field-types/Point/index.js +4 -4
- package/dist/admin/components/forms/field-types/RadioGroup/Input.js +1 -1
- package/dist/admin/components/forms/field-types/Relationship/index.js +1 -1
- package/dist/admin/components/forms/field-types/RichText/RichText.js +2 -2
- package/dist/admin/components/forms/field-types/RichText/elements/upload/Element/EditModal/index.js +3 -3
- package/dist/admin/components/forms/field-types/RichText/elements/upload/Element/EditModal/index.scss +1 -15
- package/dist/admin/components/forms/field-types/RichText/elements/upload/Element/index.scss +12 -1
- package/dist/admin/components/forms/field-types/RichText/index.scss +7 -0
- package/dist/admin/components/forms/field-types/Select/Input.d.ts +1 -0
- package/dist/admin/components/forms/field-types/Select/Input.js +4 -4
- package/dist/admin/components/forms/field-types/Select/index.js +6 -3
- package/dist/admin/components/forms/field-types/Tabs/index.scss +3 -4
- package/dist/admin/components/forms/field-types/Text/Input.js +2 -2
- package/dist/admin/components/forms/field-types/Textarea/Input.js +2 -2
- package/dist/admin/components/forms/field-types/Upload/Input.js +1 -1
- package/dist/admin/components/forms/field-types/Upload/index.scss +1 -1
- package/dist/admin/components/views/Global/Default.js +1 -1
- package/dist/admin/components/views/Version/RenderFieldsToDiff/fields/Iterable/index.js +2 -2
- package/dist/admin/components/views/Version/RenderFieldsToDiff/fields/styles.d.ts +1 -0
- package/dist/admin/components/views/Version/RenderFieldsToDiff/fields/styles.js +1 -0
- package/dist/admin/components/views/Version/Version.js +1 -1
- package/dist/admin/scss/type.scss +1 -1
- package/dist/collections/operations/local/restoreVersion.d.ts +0 -1
- package/dist/collections/operations/local/restoreVersion.js +2 -3
- package/dist/fields/config/schema.js +4 -1
- package/dist/fields/config/types.d.ts +3 -0
- package/dist/fields/config/types.js +1 -1
- package/dist/fields/hooks/beforeChange/promise.js +3 -3
- package/dist/globals/operations/local/restoreVersion.d.ts +2 -0
- package/dist/globals/operations/local/restoreVersion.js +6 -3
- package/dist/index.js +1 -1
- package/dist/mongoose/buildSchema.js +2 -3
- package/dist/webpack/getBaseConfig.js +2 -6
- package/docs/admin/overview.mdx +4 -0
- package/docs/authentication/config.mdx +49 -18
- package/docs/fields/select.mdx +40 -22
- package/docs/fields/tabs.mdx +64 -2
- package/package.json +7 -12
- package/dist/auth/auth.spec.d.ts +0 -1
- package/dist/auth/auth.spec.js +0 -198
- package/dist/collections/graphql/resolvers/resolvers.spec.d.ts +0 -1
- package/dist/collections/graphql/resolvers/resolvers.spec.js +0 -360
- package/dist/collections/operations/local/local.spec.d.ts +0 -1
- package/dist/collections/operations/local/local.spec.js +0 -196
- package/dist/collections/tests/collections.spec.d.ts +0 -1
- package/dist/collections/tests/collections.spec.js +0 -736
- package/dist/collections/tests/defaultValue.spec.d.ts +0 -1
- package/dist/collections/tests/defaultValue.spec.js +0 -95
- package/dist/collections/tests/endpoints.spec.d.ts +0 -1
- package/dist/collections/tests/endpoints.spec.js +0 -71
- package/dist/collections/tests/hooks.spec.d.ts +0 -1
- package/dist/collections/tests/hooks.spec.js +0 -156
- package/dist/collections/tests/pointField.spec.d.ts +0 -1
- package/dist/collections/tests/pointField.spec.js +0 -219
- package/dist/collections/tests/relationships.spec.d.ts +0 -1
- package/dist/collections/tests/relationships.spec.js +0 -194
- package/dist/express/middleware/errorHandler.spec.d.ts +0 -1
- package/dist/express/middleware/errorHandler.spec.js +0 -91
- package/dist/globals/requestHandlers/globals.spec.d.ts +0 -4
- package/dist/globals/requestHandlers/globals.spec.js +0 -174
- package/dist/preferences/graphql/resolvers.spec.d.ts +0 -1
- package/dist/preferences/graphql/resolvers.spec.js +0 -115
- package/dist/versions/tests/collections-graphql.spec.d.ts +0 -1
- package/dist/versions/tests/collections-graphql.spec.js +0 -141
- package/dist/versions/tests/collections-rest.spec.d.ts +0 -1
- package/dist/versions/tests/collections-rest.spec.js +0 -148
- package/dist/versions/tests/globals-graphql.spec.d.ts +0 -1
- package/dist/versions/tests/globals-graphql.spec.js +0 -157
- package/dist/versions/tests/globals-rest.spec.d.ts +0 -1
- package/dist/versions/tests/globals-rest.spec.js +0 -151
package/docs/fields/select.mdx
CHANGED
|
@@ -6,40 +6,55 @@ desc: The Select field provides a dropdown-style interface for choosing options
|
|
|
6
6
|
keywords: select, multi-select, fields, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react, express
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
<Banner
|
|
10
|
-
The Select field provides a dropdown-style interface for choosing options from
|
|
9
|
+
<Banner>
|
|
10
|
+
The Select field provides a dropdown-style interface for choosing options from
|
|
11
|
+
a predefined list as an enumeration.
|
|
11
12
|
</Banner>
|
|
12
13
|
|
|
13
14
|
### Config
|
|
14
15
|
|
|
15
|
-
| Option
|
|
16
|
-
|
|
|
17
|
-
| **`name`**
|
|
18
|
-
| **`options`**
|
|
19
|
-
| **`hasMany`**
|
|
20
|
-
| **`label`**
|
|
21
|
-
| **`unique`**
|
|
22
|
-
| **`validate`**
|
|
23
|
-
| **`index`**
|
|
24
|
-
| **`saveToJWT`**
|
|
25
|
-
| **`hooks`**
|
|
26
|
-
| **`access`**
|
|
27
|
-
| **`hidden`**
|
|
28
|
-
| **`defaultValue`**
|
|
29
|
-
| **`localized`**
|
|
30
|
-
| **`required`**
|
|
31
|
-
| **`admin`**
|
|
16
|
+
| Option | Description |
|
|
17
|
+
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
18
|
+
| **`name`** \* | To be used as the property name when stored and retrieved from the database. |
|
|
19
|
+
| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing a `label` string and a `value` string. |
|
|
20
|
+
| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many selections instead of only one. |
|
|
21
|
+
| **`label`** | Used as a field label in the Admin panel and to name the generated GraphQL type. |
|
|
22
|
+
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
|
23
|
+
| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
|
|
24
|
+
| **`index`** | Build a [MongoDB index](https://docs.mongodb.com/manual/indexes/) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
|
25
|
+
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
|
|
26
|
+
| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
|
|
27
|
+
| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
|
|
28
|
+
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
|
|
29
|
+
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
|
30
|
+
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
|
31
|
+
| **`required`** | Require this field to have a value. |
|
|
32
|
+
| **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-config) for more details. |
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
_\* An asterisk denotes that a property is required._
|
|
34
35
|
|
|
35
36
|
<Banner type="warning">
|
|
36
|
-
<strong>Important:</strong
|
|
37
|
-
|
|
37
|
+
<strong>Important:</strong>
|
|
38
|
+
<br />
|
|
39
|
+
Option values should be strings that do not contain hyphens or special
|
|
40
|
+
characters due to GraphQL enumeration naming constraints. Underscores are
|
|
41
|
+
allowed. If you determine you need your option values to be non-strings or
|
|
42
|
+
contain special characters, they will be formatted accordingly before being
|
|
43
|
+
used as a GraphQL enum.
|
|
38
44
|
</Banner>
|
|
39
45
|
|
|
46
|
+
### Admin config
|
|
47
|
+
|
|
48
|
+
In addition to the default [field admin config](/docs/fields/overview#admin-config), the Select field type also allows for the following admin-specific properties:
|
|
49
|
+
|
|
50
|
+
**`isClearable`**
|
|
51
|
+
|
|
52
|
+
Set to `true` if you'd like this field to be clearable within the Admin UI.
|
|
53
|
+
|
|
40
54
|
### Example
|
|
41
55
|
|
|
42
56
|
`collections/ExampleCollection.js`
|
|
57
|
+
|
|
43
58
|
```js
|
|
44
59
|
{
|
|
45
60
|
slug: 'example-collection',
|
|
@@ -48,6 +63,9 @@ keywords: select, multi-select, fields, config, configuration, documentation, Co
|
|
|
48
63
|
name: 'selectedFeatures', // required
|
|
49
64
|
type: 'select', // required
|
|
50
65
|
hasMany: true,
|
|
66
|
+
admin: {
|
|
67
|
+
isClearable: true,
|
|
68
|
+
},
|
|
51
69
|
options: [
|
|
52
70
|
{
|
|
53
71
|
label: 'Metallic Paint',
|
package/docs/fields/tabs.mdx
CHANGED
|
@@ -2,8 +2,70 @@
|
|
|
2
2
|
title: Tabs Field
|
|
3
3
|
label: Tabs
|
|
4
4
|
order: 170
|
|
5
|
-
desc: Tabs field
|
|
5
|
+
desc: The Tabs field is a great way to organize complex editing experiences into specific tab-based areas.
|
|
6
6
|
keywords: tabs, fields, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react, express
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
<Banner >
|
|
10
|
+
The Tabs field is presentational-only and only affects the Admin panel. By using it, you can place fields within a nice layout component that separates certain sub-fields by a tabbed interface.
|
|
11
|
+
</Banner>
|
|
12
|
+
|
|
13
|
+

|
|
14
|
+
*Tabs field type used to separate Hero fields from Page Layout*
|
|
15
|
+
|
|
16
|
+
### Config
|
|
17
|
+
|
|
18
|
+
| Option | Description |
|
|
19
|
+
| ---------------- | ----------- |
|
|
20
|
+
| **`tabs`** * | Array of tabs to render within this Tabs field. |
|
|
21
|
+
| **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-config) for more details. |
|
|
22
|
+
|
|
23
|
+
#### Tab-specific Config
|
|
24
|
+
|
|
25
|
+
Each tab has its own required `label` and `fields` array. You can also optionally pass a `description` to render within each individual tab.
|
|
26
|
+
|
|
27
|
+
| Option | Description |
|
|
28
|
+
| ----------------- | ----------- |
|
|
29
|
+
| **`label`** * | The label to render on the tab itself. |
|
|
30
|
+
| **`fields`** * | The fields to render within this tab. |
|
|
31
|
+
| **`description`** | Optionally render a description within this tab to describe the contents of the tab itself. |
|
|
32
|
+
|
|
33
|
+
*\* An asterisk denotes that a property is required.*
|
|
34
|
+
|
|
35
|
+
### Example
|
|
36
|
+
|
|
37
|
+
`collections/ExampleCollection.js`
|
|
38
|
+
```js
|
|
39
|
+
{
|
|
40
|
+
slug: 'example-collection',
|
|
41
|
+
fields: [
|
|
42
|
+
{
|
|
43
|
+
type: 'tabs', // required
|
|
44
|
+
tabs: [ // required
|
|
45
|
+
{
|
|
46
|
+
label: 'Tab One Label', // required
|
|
47
|
+
description: 'This will appear within the tab above the fields.'
|
|
48
|
+
fields: [ // required
|
|
49
|
+
{
|
|
50
|
+
name: 'someTextField',
|
|
51
|
+
type: 'text',
|
|
52
|
+
required: true,
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
label: 'Tab Two Label', // required
|
|
58
|
+
fields: [ // required
|
|
59
|
+
{
|
|
60
|
+
name: 'numberField',
|
|
61
|
+
type: 'number',
|
|
62
|
+
required: true,
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payload",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Node, React and MongoDB Headless CMS and Application Framework",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -32,20 +32,15 @@
|
|
|
32
32
|
"build:components": "webpack --config dist/webpack/components.config.js",
|
|
33
33
|
"build": "yarn copyfiles && yarn build:tsc && yarn build:components",
|
|
34
34
|
"build:watch": "nodemon --watch 'src/**' --ext 'ts,tsx' --exec 'yarn build:tsc'",
|
|
35
|
-
"demo:build:analyze": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.ts PAYLOAD_ANALYZE_BUNDLE=true node dist/bin/build",
|
|
36
|
-
"demo:build": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.ts node dist/bin/build",
|
|
37
|
-
"demo:generate:types": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.ts node dist/bin/generateTypes",
|
|
38
|
-
"demo:generate:graphqlschema": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.ts node dist/bin/generateGraphQLSchema",
|
|
39
|
-
"demo:serve": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.ts NODE_ENV=production nodemon",
|
|
40
35
|
"dev": "nodemon",
|
|
41
|
-
"dev:
|
|
36
|
+
"dev:generate-types": "node ./test/generateTypes.js",
|
|
42
37
|
"pretest": "yarn build",
|
|
43
38
|
"test": "yarn test:int && yarn test:components",
|
|
44
|
-
"test:int": "cross-env
|
|
45
|
-
"test:e2e": "cross-env
|
|
46
|
-
"test:e2e:headed": "cross-env
|
|
47
|
-
"test:e2e:debug": "cross-env PWDEBUG=1
|
|
48
|
-
"test:components": "cross-env
|
|
39
|
+
"test:int": "cross-env DISABLE_LOGGING=true jest --forceExit --detectOpenHandles",
|
|
40
|
+
"test:e2e": "cross-env DISABLE_LOGGING=true playwright test",
|
|
41
|
+
"test:e2e:headed": "cross-env DISABLE_LOGGING=true playwright test --headed",
|
|
42
|
+
"test:e2e:debug": "cross-env PWDEBUG=1 DISABLE_LOGGING=true playwright test",
|
|
43
|
+
"test:components": "cross-env jest --config=jest.components.config.js",
|
|
49
44
|
"clean": "rimraf dist",
|
|
50
45
|
"release": "release-it",
|
|
51
46
|
"release:patch": "release-it patch",
|
package/dist/auth/auth.spec.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/auth/auth.spec.js
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const mongodb_1 = __importDefault(require("mongodb"));
|
|
7
|
-
const load_1 = __importDefault(require("../config/load"));
|
|
8
|
-
const testCredentials_1 = require("../mongoose/testCredentials");
|
|
9
|
-
require('isomorphic-fetch');
|
|
10
|
-
const { url: mongoURL, port: mongoPort, name: mongoDBName } = testCredentials_1.connection;
|
|
11
|
-
const { serverURL: url } = (0, load_1.default)();
|
|
12
|
-
let token = null;
|
|
13
|
-
describe('Users REST API', () => {
|
|
14
|
-
it('should prevent registering a first user', async () => {
|
|
15
|
-
const response = await fetch(`${url}/api/admins/first-register`, {
|
|
16
|
-
body: JSON.stringify({
|
|
17
|
-
email: 'thisuser@shouldbeprevented.com',
|
|
18
|
-
password: 'get-out',
|
|
19
|
-
}),
|
|
20
|
-
headers: {
|
|
21
|
-
'Content-Type': 'application/json',
|
|
22
|
-
},
|
|
23
|
-
method: 'post',
|
|
24
|
-
});
|
|
25
|
-
expect(response.status).toBe(403);
|
|
26
|
-
});
|
|
27
|
-
it('should login a user successfully', async () => {
|
|
28
|
-
const response = await fetch(`${url}/api/admins/login`, {
|
|
29
|
-
body: JSON.stringify({
|
|
30
|
-
email: testCredentials_1.email,
|
|
31
|
-
password: testCredentials_1.password,
|
|
32
|
-
}),
|
|
33
|
-
headers: {
|
|
34
|
-
'Content-Type': 'application/json',
|
|
35
|
-
},
|
|
36
|
-
method: 'post',
|
|
37
|
-
});
|
|
38
|
-
const data = await response.json();
|
|
39
|
-
expect(response.status).toBe(200);
|
|
40
|
-
expect(data.token).toBeDefined();
|
|
41
|
-
({ token } = data);
|
|
42
|
-
});
|
|
43
|
-
it('should return a logged in user from /me', async () => {
|
|
44
|
-
const response = await fetch(`${url}/api/admins/me`, {
|
|
45
|
-
headers: {
|
|
46
|
-
Authorization: `JWT ${token}`,
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
const data = await response.json();
|
|
50
|
-
expect(response.status).toBe(200);
|
|
51
|
-
expect(data.user.email).toBeDefined();
|
|
52
|
-
});
|
|
53
|
-
it('should refresh a token and reset its expiration', async () => {
|
|
54
|
-
const response = await fetch(`${url}/api/admins/refresh-token`, {
|
|
55
|
-
method: 'post',
|
|
56
|
-
headers: {
|
|
57
|
-
Authorization: `JWT ${token}`,
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
const data = await response.json();
|
|
61
|
-
expect(response.status).toBe(200);
|
|
62
|
-
expect(data.refreshedToken).toBeDefined();
|
|
63
|
-
token = data.refreshedToken;
|
|
64
|
-
});
|
|
65
|
-
it('should allow forgot-password by email', async () => {
|
|
66
|
-
// TODO: figure out how to spy on payload instance functions
|
|
67
|
-
// const mailSpy = jest.spyOn(payload, 'sendEmail');
|
|
68
|
-
const response = await fetch(`${url}/api/admins/forgot-password`, {
|
|
69
|
-
method: 'post',
|
|
70
|
-
body: JSON.stringify({
|
|
71
|
-
email: testCredentials_1.email,
|
|
72
|
-
}),
|
|
73
|
-
headers: {
|
|
74
|
-
'Content-Type': 'application/json',
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
// is not working
|
|
78
|
-
// expect(mailSpy).toHaveBeenCalled();
|
|
79
|
-
expect(response.status).toBe(200);
|
|
80
|
-
});
|
|
81
|
-
it('should allow a user to be created', async () => {
|
|
82
|
-
const response = await fetch(`${url}/api/admins`, {
|
|
83
|
-
body: JSON.stringify({
|
|
84
|
-
email: 'name@test.com',
|
|
85
|
-
password: testCredentials_1.password,
|
|
86
|
-
roles: ['editor'],
|
|
87
|
-
}),
|
|
88
|
-
headers: {
|
|
89
|
-
Authorization: `JWT ${token}`,
|
|
90
|
-
'Content-Type': 'application/json',
|
|
91
|
-
},
|
|
92
|
-
method: 'post',
|
|
93
|
-
});
|
|
94
|
-
const data = await response.json();
|
|
95
|
-
expect(response.status).toBe(201);
|
|
96
|
-
expect(data).toHaveProperty('message');
|
|
97
|
-
expect(data).toHaveProperty('doc');
|
|
98
|
-
const { doc } = data;
|
|
99
|
-
expect(doc).toHaveProperty('email');
|
|
100
|
-
expect(doc).toHaveProperty('createdAt');
|
|
101
|
-
expect(doc).toHaveProperty('roles');
|
|
102
|
-
});
|
|
103
|
-
it('should allow verification of a user', async () => {
|
|
104
|
-
const emailToVerify = 'verify@me.com';
|
|
105
|
-
const response = await fetch(`${url}/api/public-users`, {
|
|
106
|
-
body: JSON.stringify({
|
|
107
|
-
email: emailToVerify,
|
|
108
|
-
password: testCredentials_1.password,
|
|
109
|
-
roles: ['editor'],
|
|
110
|
-
}),
|
|
111
|
-
headers: {
|
|
112
|
-
Authorization: `JWT ${token}`,
|
|
113
|
-
'Content-Type': 'application/json',
|
|
114
|
-
},
|
|
115
|
-
method: 'post',
|
|
116
|
-
});
|
|
117
|
-
expect(response.status).toBe(201);
|
|
118
|
-
const client = await mongodb_1.default.connect(`${mongoURL}:${mongoPort}`, {
|
|
119
|
-
useUnifiedTopology: true,
|
|
120
|
-
});
|
|
121
|
-
const db = client.db(mongoDBName);
|
|
122
|
-
const userResult = await db.collection('public-users').findOne({ email: emailToVerify });
|
|
123
|
-
const { _verified, _verificationToken } = userResult;
|
|
124
|
-
expect(_verified).toBe(false);
|
|
125
|
-
expect(_verificationToken).toBeDefined();
|
|
126
|
-
const verificationResponse = await fetch(`${url}/api/public-users/verify/${_verificationToken}`, {
|
|
127
|
-
headers: {
|
|
128
|
-
'Content-Type': 'application/json',
|
|
129
|
-
},
|
|
130
|
-
method: 'post',
|
|
131
|
-
});
|
|
132
|
-
expect(verificationResponse.status).toBe(200);
|
|
133
|
-
const afterVerifyResult = await db.collection('public-users').findOne({ email: emailToVerify });
|
|
134
|
-
const { _verified: afterVerified, _verificationToken: afterToken } = afterVerifyResult;
|
|
135
|
-
expect(afterVerified).toBe(true);
|
|
136
|
-
expect(afterToken).toBeUndefined();
|
|
137
|
-
});
|
|
138
|
-
describe('Account Locking', () => {
|
|
139
|
-
const userEmail = 'lock@me.com';
|
|
140
|
-
let db;
|
|
141
|
-
beforeAll(async () => {
|
|
142
|
-
const client = await mongodb_1.default.connect(`${mongoURL}:${mongoPort}`);
|
|
143
|
-
db = client.db(mongoDBName);
|
|
144
|
-
});
|
|
145
|
-
it('should lock the user after too many attempts', async () => {
|
|
146
|
-
await fetch(`${url}/api/admins`, {
|
|
147
|
-
body: JSON.stringify({
|
|
148
|
-
email: userEmail,
|
|
149
|
-
password: testCredentials_1.password,
|
|
150
|
-
}),
|
|
151
|
-
headers: {
|
|
152
|
-
Authorization: `JWT ${token}`,
|
|
153
|
-
'Content-Type': 'application/json',
|
|
154
|
-
},
|
|
155
|
-
method: 'post',
|
|
156
|
-
});
|
|
157
|
-
const tryLogin = () => fetch(`${url}/api/admins/login`, {
|
|
158
|
-
body: JSON.stringify({
|
|
159
|
-
email: userEmail,
|
|
160
|
-
password: 'bad',
|
|
161
|
-
}),
|
|
162
|
-
headers: {
|
|
163
|
-
Authorization: `JWT ${token}`,
|
|
164
|
-
'Content-Type': 'application/json',
|
|
165
|
-
},
|
|
166
|
-
method: 'post',
|
|
167
|
-
});
|
|
168
|
-
await tryLogin();
|
|
169
|
-
await tryLogin();
|
|
170
|
-
await tryLogin();
|
|
171
|
-
await tryLogin();
|
|
172
|
-
await tryLogin();
|
|
173
|
-
const userResult = await db.collection('admins').findOne({ email: userEmail });
|
|
174
|
-
const { loginAttempts, lockUntil } = userResult;
|
|
175
|
-
expect(loginAttempts).toBe(5);
|
|
176
|
-
expect(lockUntil).toBeDefined();
|
|
177
|
-
});
|
|
178
|
-
it('should unlock account once lockUntil period is over', async () => {
|
|
179
|
-
await db.collection('admins').findOneAndUpdate({ email: userEmail }, { $set: { lockUntil: Date.now() - (605 * 1000) } });
|
|
180
|
-
await fetch(`${url}/api/admins/login`, {
|
|
181
|
-
body: JSON.stringify({
|
|
182
|
-
email: userEmail,
|
|
183
|
-
password: testCredentials_1.password,
|
|
184
|
-
}),
|
|
185
|
-
headers: {
|
|
186
|
-
Authorization: `JWT ${token}`,
|
|
187
|
-
'Content-Type': 'application/json',
|
|
188
|
-
},
|
|
189
|
-
method: 'post',
|
|
190
|
-
});
|
|
191
|
-
const userResult = await db.collection('admins').findOne({ email: userEmail });
|
|
192
|
-
const { loginAttempts, lockUntil } = userResult;
|
|
193
|
-
expect(loginAttempts).toBe(0);
|
|
194
|
-
expect(lockUntil).toBeUndefined();
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5zcGVjLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2F1dGgvYXV0aC5zcGVjLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsc0RBQWtDO0FBQ2xDLDBEQUF1QztBQUN2QyxpRUFBMEU7QUFFMUUsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQUM7QUFFNUIsTUFBTSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEdBQUcsNEJBQVUsQ0FBQztBQUV6RSxNQUFNLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUEsY0FBUyxHQUFFLENBQUM7QUFFdkMsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDO0FBRWpCLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLEVBQUU7SUFDOUIsRUFBRSxDQUFDLHlDQUF5QyxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3ZELE1BQU0sUUFBUSxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsR0FBRyw0QkFBNEIsRUFBRTtZQUMvRCxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQztnQkFDbkIsS0FBSyxFQUFFLGdDQUFnQztnQkFDdkMsUUFBUSxFQUFFLFNBQVM7YUFDcEIsQ0FBQztZQUNGLE9BQU8sRUFBRTtnQkFDUCxjQUFjLEVBQUUsa0JBQWtCO2FBQ25DO1lBQ0QsTUFBTSxFQUFFLE1BQU07U0FDZixDQUFDLENBQUM7UUFFSCxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNwQyxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxrQ0FBa0MsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNoRCxNQUFNLFFBQVEsR0FBRyxNQUFNLEtBQUssQ0FBQyxHQUFHLEdBQUcsbUJBQW1CLEVBQUU7WUFDdEQsSUFBSSxFQUFFLElBQUksQ0FBQyxT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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|