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.
Files changed (89) hide show
  1. package/CHANGELOG.md +607 -852
  2. package/components/styles.css +1 -1
  3. package/dist/admin/components/elements/Banner/index.scss +1 -0
  4. package/dist/admin/components/elements/ColumnSelector/index.scss +4 -7
  5. package/dist/admin/components/elements/Eyebrow/index.scss +4 -0
  6. package/dist/admin/components/elements/Nav/index.js +2 -2
  7. package/dist/admin/components/elements/Pill/index.scss +1 -0
  8. package/dist/admin/components/elements/ReactSelect/index.js +2 -2
  9. package/dist/admin/components/elements/ReactSelect/types.d.ts +1 -0
  10. package/dist/admin/components/forms/field-types/Array/Array.js +1 -1
  11. package/dist/admin/components/forms/field-types/Blocks/Blocks.js +1 -1
  12. package/dist/admin/components/forms/field-types/Checkbox/index.js +1 -1
  13. package/dist/admin/components/forms/field-types/Code/Code.js +1 -1
  14. package/dist/admin/components/forms/field-types/DateTime/index.js +1 -1
  15. package/dist/admin/components/forms/field-types/Email/index.js +2 -2
  16. package/dist/admin/components/forms/field-types/Group/index.js +1 -1
  17. package/dist/admin/components/forms/field-types/HiddenInput/index.js +1 -1
  18. package/dist/admin/components/forms/field-types/Number/index.js +2 -2
  19. package/dist/admin/components/forms/field-types/Password/index.js +2 -2
  20. package/dist/admin/components/forms/field-types/Point/index.js +4 -4
  21. package/dist/admin/components/forms/field-types/RadioGroup/Input.js +1 -1
  22. package/dist/admin/components/forms/field-types/Relationship/index.js +1 -1
  23. package/dist/admin/components/forms/field-types/RichText/RichText.js +2 -2
  24. package/dist/admin/components/forms/field-types/RichText/elements/upload/Element/EditModal/index.js +3 -3
  25. package/dist/admin/components/forms/field-types/RichText/elements/upload/Element/EditModal/index.scss +1 -15
  26. package/dist/admin/components/forms/field-types/RichText/elements/upload/Element/index.scss +12 -1
  27. package/dist/admin/components/forms/field-types/RichText/index.scss +7 -0
  28. package/dist/admin/components/forms/field-types/Select/Input.d.ts +1 -0
  29. package/dist/admin/components/forms/field-types/Select/Input.js +4 -4
  30. package/dist/admin/components/forms/field-types/Select/index.js +6 -3
  31. package/dist/admin/components/forms/field-types/Tabs/index.scss +3 -4
  32. package/dist/admin/components/forms/field-types/Text/Input.js +2 -2
  33. package/dist/admin/components/forms/field-types/Textarea/Input.js +2 -2
  34. package/dist/admin/components/forms/field-types/Upload/Input.js +1 -1
  35. package/dist/admin/components/forms/field-types/Upload/index.scss +1 -1
  36. package/dist/admin/components/views/Global/Default.js +1 -1
  37. package/dist/admin/components/views/Version/RenderFieldsToDiff/fields/Iterable/index.js +2 -2
  38. package/dist/admin/components/views/Version/RenderFieldsToDiff/fields/styles.d.ts +1 -0
  39. package/dist/admin/components/views/Version/RenderFieldsToDiff/fields/styles.js +1 -0
  40. package/dist/admin/components/views/Version/Version.js +1 -1
  41. package/dist/admin/scss/type.scss +1 -1
  42. package/dist/collections/operations/local/restoreVersion.d.ts +0 -1
  43. package/dist/collections/operations/local/restoreVersion.js +2 -3
  44. package/dist/fields/config/schema.js +4 -1
  45. package/dist/fields/config/types.d.ts +3 -0
  46. package/dist/fields/config/types.js +1 -1
  47. package/dist/fields/hooks/beforeChange/promise.js +3 -3
  48. package/dist/globals/operations/local/restoreVersion.d.ts +2 -0
  49. package/dist/globals/operations/local/restoreVersion.js +6 -3
  50. package/dist/index.js +1 -1
  51. package/dist/mongoose/buildSchema.js +2 -3
  52. package/dist/webpack/getBaseConfig.js +2 -6
  53. package/docs/admin/overview.mdx +4 -0
  54. package/docs/authentication/config.mdx +49 -18
  55. package/docs/fields/select.mdx +40 -22
  56. package/docs/fields/tabs.mdx +64 -2
  57. package/package.json +7 -12
  58. package/dist/auth/auth.spec.d.ts +0 -1
  59. package/dist/auth/auth.spec.js +0 -198
  60. package/dist/collections/graphql/resolvers/resolvers.spec.d.ts +0 -1
  61. package/dist/collections/graphql/resolvers/resolvers.spec.js +0 -360
  62. package/dist/collections/operations/local/local.spec.d.ts +0 -1
  63. package/dist/collections/operations/local/local.spec.js +0 -196
  64. package/dist/collections/tests/collections.spec.d.ts +0 -1
  65. package/dist/collections/tests/collections.spec.js +0 -736
  66. package/dist/collections/tests/defaultValue.spec.d.ts +0 -1
  67. package/dist/collections/tests/defaultValue.spec.js +0 -95
  68. package/dist/collections/tests/endpoints.spec.d.ts +0 -1
  69. package/dist/collections/tests/endpoints.spec.js +0 -71
  70. package/dist/collections/tests/hooks.spec.d.ts +0 -1
  71. package/dist/collections/tests/hooks.spec.js +0 -156
  72. package/dist/collections/tests/pointField.spec.d.ts +0 -1
  73. package/dist/collections/tests/pointField.spec.js +0 -219
  74. package/dist/collections/tests/relationships.spec.d.ts +0 -1
  75. package/dist/collections/tests/relationships.spec.js +0 -194
  76. package/dist/express/middleware/errorHandler.spec.d.ts +0 -1
  77. package/dist/express/middleware/errorHandler.spec.js +0 -91
  78. package/dist/globals/requestHandlers/globals.spec.d.ts +0 -4
  79. package/dist/globals/requestHandlers/globals.spec.js +0 -174
  80. package/dist/preferences/graphql/resolvers.spec.d.ts +0 -1
  81. package/dist/preferences/graphql/resolvers.spec.js +0 -115
  82. package/dist/versions/tests/collections-graphql.spec.d.ts +0 -1
  83. package/dist/versions/tests/collections-graphql.spec.js +0 -141
  84. package/dist/versions/tests/collections-rest.spec.d.ts +0 -1
  85. package/dist/versions/tests/collections-rest.spec.js +0 -148
  86. package/dist/versions/tests/globals-graphql.spec.d.ts +0 -1
  87. package/dist/versions/tests/globals-graphql.spec.js +0 -157
  88. package/dist/versions/tests/globals-rest.spec.d.ts +0 -1
  89. package/dist/versions/tests/globals-rest.spec.js +0 -151
@@ -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 a predefined list as an enumeration.
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 | Description |
16
- | ---------------- | ----------- |
17
- | **`name`** * | To be used as the property name when stored and retrieved from the database. |
18
- | **`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. |
19
- | **`hasMany`** | Boolean when, if set to `true`, allows this field to have many selections instead of only one. |
20
- | **`label`** | Used as a field label in the Admin panel and to name the generated GraphQL type. |
21
- | **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
22
- | **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
23
- | **`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. |
24
- | **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
25
- | **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
26
- | **`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) |
27
- | **`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. |
28
- | **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
29
- | **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
30
- | **`required`** | Require this field to have a value. |
31
- | **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-config) for more details. |
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
- *\* An asterisk denotes that a property is required.*
34
+ _\* An asterisk denotes that a property is required._
34
35
 
35
36
  <Banner type="warning">
36
- <strong>Important:</strong><br/>
37
- Option values should be strings that do not contain hyphens or special characters due to GraphQL enumeration naming constraints. Underscores are allowed. If you determine you need your option values to be non-strings or contain special characters, they will be formatted accordingly before being used as a GraphQL enum.
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',
@@ -2,8 +2,70 @@
2
2
  title: Tabs Field
3
3
  label: Tabs
4
4
  order: 170
5
- desc: Tabs field desc here
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
- Coming soon
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
+ ![Tabs field type used to separate Hero fields from Page Layout](https://payloadcms.com/images/fields/tabs/tabs.jpg)
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.20.8-beta.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:generatetypes": "node ./test/generateTypes.js",
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 NODE_ENV=test DISABLE_LOGGING=true jest --forceExit --detectOpenHandles",
45
- "test:e2e": "cross-env NODE_ENV=test DISABLE_LOGGING=true playwright test",
46
- "test:e2e:headed": "cross-env NODE_ENV=test DISABLE_LOGGING=true playwright test --headed",
47
- "test:e2e:debug": "cross-env PWDEBUG=1 NODE_ENV=test DISABLE_LOGGING=true playwright test",
48
- "test:components": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.ts NODE_ENV=test jest --config=jest.components.config.js",
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",
@@ -1 +0,0 @@
1
- export {};
@@ -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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