@madauth/server 0.1.0 → 0.2.0-beta.2
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 +17 -7
- package/dist/bin.js +284 -22
- package/dist/{chunk-V2XKGETK.js → chunk-5CKEMC6M.js} +163 -28
- package/dist/{chunk-AVZE6FFR.js → chunk-6EJDVZCD.js} +8 -3
- package/dist/{chunk-PRRKLEW7.js → chunk-7CTAB3QV.js} +21 -0
- package/dist/{chunk-3WIWWKRI.js → chunk-CNL562LZ.js} +17 -42
- package/dist/chunk-XNBWZZHT.js +60 -0
- package/dist/{chunk-TEMZRMFF.js → chunk-YALS7OMV.js} +162 -42
- package/dist/{config-KQvE2imU.d.ts → config-BkxADgtp.d.ts} +16 -4
- package/dist/dynamodb.js +244 -0
- package/dist/entry/azure.d.ts +5 -5
- package/dist/entry/azure.js +9 -7
- package/dist/entry/lambda.d.ts +5 -5
- package/dist/entry/lambda.js +9 -7
- package/dist/entry/node.d.ts +5 -8
- package/dist/entry/node.js +8 -6
- package/dist/index.d.ts +12 -7
- package/dist/index.js +12 -8
- package/dist/{schema-Dotc6LU7.d.ts → schema-BSgYVRpd.d.ts} +28 -1
- package/dist/sqlite.js +7 -4
- package/dist/standalone/azure.mjs +611 -78
- package/dist/standalone/lambda.mjs +611 -78
- package/dist/standalone/main.mjs +29508 -592
- package/dist/store/dynamodb.d.ts +19 -0
- package/dist/store/sqlite.d.ts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +65 -2
- package/dist/{user-3DDyggFV.d.ts → user-C1A3BfOo.d.ts} +2 -0
- package/dist/verify.d.ts +1 -1
- package/dist/verify.js +1 -1
- package/dist/{webhook-CT80emTQ.d.ts → webhook-ltwulgcB.d.ts} +3 -3
- package/dist/webhook.d.ts +1 -1
- package/dist/webhook.js +1 -1
- package/package.json +12 -2
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
|
|
2
|
+
import { S as StoreAdapter } from '../schema-BSgYVRpd.js';
|
|
3
|
+
|
|
4
|
+
interface DynamoDbAdapterOptions {
|
|
5
|
+
/** The table, with the partition key `pk` and the sort key `sk` (both strings). */
|
|
6
|
+
tableName: string;
|
|
7
|
+
/** Default: a client with the region and credentials of the environment. */
|
|
8
|
+
client?: Pick<DynamoDBClient, 'send'>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Stores madAuth's records in one DynamoDB table. Create the table yourself, with the partition key `pk`
|
|
12
|
+
* and the sort key `sk`, both of type string (see "DynamoDB" in docs/server.md).
|
|
13
|
+
*
|
|
14
|
+
* A filter must contain the record's id, a unique field or an indexed field: the adapter never scans the
|
|
15
|
+
* table. Unique and indexed fields can't be changed by `update`.
|
|
16
|
+
*/
|
|
17
|
+
declare function createDynamoDbAdapter(options: DynamoDbAdapterOptions): StoreAdapter;
|
|
18
|
+
|
|
19
|
+
export { type DynamoDbAdapterOptions, createDynamoDbAdapter };
|
package/dist/store/sqlite.d.ts
CHANGED
package/dist/testing.d.ts
CHANGED
package/dist/testing.js
CHANGED
|
@@ -13,12 +13,26 @@ function testUser(overrides = {}) {
|
|
|
13
13
|
name: null,
|
|
14
14
|
sessionVersion: 0,
|
|
15
15
|
lastMailAt: 0,
|
|
16
|
+
wrongCodes: 0,
|
|
16
17
|
createdAt: 17e11,
|
|
17
18
|
...overrides
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
|
-
function
|
|
21
|
-
|
|
21
|
+
function testAccount(overrides = {}) {
|
|
22
|
+
const id = unique("acc_contract");
|
|
23
|
+
return {
|
|
24
|
+
id,
|
|
25
|
+
userId: unique("usr_contract"),
|
|
26
|
+
key: `password:${id}`,
|
|
27
|
+
secret: "hash",
|
|
28
|
+
failedAttempts: 0,
|
|
29
|
+
lockedUntil: 0,
|
|
30
|
+
createdAt: 17e11,
|
|
31
|
+
...overrides
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function testVerification(userId, purpose = "reset") {
|
|
35
|
+
return { id: unique("ver"), userId, purpose, codeHash: "h", attempts: 0, expiresAt: 17e11 };
|
|
22
36
|
}
|
|
23
37
|
function storeAdapterContract(t, createAdapter) {
|
|
24
38
|
const { describe, it, expect } = t;
|
|
@@ -92,6 +106,55 @@ function storeAdapterContract(t, createAdapter) {
|
|
|
92
106
|
const counts = await Promise.all(Array.from({ length: 10 }, () => store.delete("verification", { id: record.id })));
|
|
93
107
|
expect(counts.reduce((sum, n) => sum + n, 0)).toBe(1);
|
|
94
108
|
});
|
|
109
|
+
it("finds a record by a unique field other than its id", async () => {
|
|
110
|
+
const store = await createAdapter();
|
|
111
|
+
const account = testAccount();
|
|
112
|
+
await store.create("account", account);
|
|
113
|
+
expect(await store.findOne("account", { key: account.key })).toEqual(account);
|
|
114
|
+
expect(await store.findOne("account", { key: unique("password:missing") })).toBe(null);
|
|
115
|
+
});
|
|
116
|
+
it("sets a field to a value and to null", async () => {
|
|
117
|
+
const store = await createAdapter();
|
|
118
|
+
const user = testUser({ name: "Ada" });
|
|
119
|
+
await store.create("user", user);
|
|
120
|
+
expect(await store.update("user", { id: user.id }, { name: "Grace" })).toBe(1);
|
|
121
|
+
expect((await store.findOne("user", { id: user.id }))?.name).toBe("Grace");
|
|
122
|
+
expect(await store.update("user", { id: user.id }, { name: null })).toBe(1);
|
|
123
|
+
expect(await store.findOne("user", { id: user.id })).toEqual({ ...user, name: null });
|
|
124
|
+
expect(await store.update("user", { id: user.id, name: null }, { name: "Ada" })).toBe(1);
|
|
125
|
+
expect(await store.update("user", { id: user.id, name: null }, { name: "Grace" })).toBe(0);
|
|
126
|
+
expect((await store.findOne("user", { id: user.id }))?.name).toBe("Ada");
|
|
127
|
+
});
|
|
128
|
+
it("updates a record only while it still matches every field of the filter", async () => {
|
|
129
|
+
const store = await createAdapter();
|
|
130
|
+
const account = testAccount();
|
|
131
|
+
await store.create("account", account);
|
|
132
|
+
const unchanged = { id: account.id, failedAttempts: 0 };
|
|
133
|
+
expect(await store.update("account", unchanged, { failedAttempts: 1, lockedUntil: 5 })).toBe(1);
|
|
134
|
+
expect(await store.update("account", unchanged, { failedAttempts: 1, lockedUntil: 9 })).toBe(0);
|
|
135
|
+
expect(await store.findOne("account", { id: account.id })).toEqual({ ...account, failedAttempts: 1, lockedUntil: 5 });
|
|
136
|
+
});
|
|
137
|
+
it("applies only one of several concurrent updates with the same filter", async () => {
|
|
138
|
+
const store = await createAdapter();
|
|
139
|
+
const account = testAccount();
|
|
140
|
+
await store.create("account", account);
|
|
141
|
+
const counts = await Promise.all(
|
|
142
|
+
Array.from({ length: 10 }, () => store.update("account", { id: account.id, failedAttempts: 0 }, { failedAttempts: 1 }))
|
|
143
|
+
);
|
|
144
|
+
expect(counts.reduce((sum, n) => sum + n, 0)).toBe(1);
|
|
145
|
+
});
|
|
146
|
+
it("deletes every record that matches an indexed field", async () => {
|
|
147
|
+
const store = await createAdapter();
|
|
148
|
+
const userId = unique("usr_contract");
|
|
149
|
+
const other = testVerification(unique("usr_contract"));
|
|
150
|
+
for (const purpose of ["verify", "reset", "reset"]) await store.create("verification", testVerification(userId, purpose));
|
|
151
|
+
await store.create("verification", other);
|
|
152
|
+
expect(await store.delete("verification", { userId, purpose: "verify" })).toBe(1);
|
|
153
|
+
expect((await store.findMany("verification", { userId })).length).toBe(2);
|
|
154
|
+
expect(await store.delete("verification", { userId })).toBe(2);
|
|
155
|
+
expect(await store.findMany("verification", { userId })).toEqual([]);
|
|
156
|
+
expect(await store.findOne("verification", { id: other.id })).toEqual(other);
|
|
157
|
+
});
|
|
95
158
|
});
|
|
96
159
|
}
|
|
97
160
|
export {
|
package/dist/verify.d.ts
CHANGED
package/dist/verify.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Every `type` madAuth sends. */
|
|
2
|
-
declare const WEBHOOK_TYPES: readonly ["email.verify", "email.reset", "email.already_registered", "signup.before", "user.created", "email.verified", "password.reset", "user.signed_in"];
|
|
2
|
+
declare const WEBHOOK_TYPES: readonly ["email.verify", "email.reset", "email.already_registered", "signup.before", "user.created", "email.verified", "password.reset", "user.signed_in", "user.deleted", "roles.changed"];
|
|
3
3
|
type WebhookType = (typeof WEBHOOK_TYPES)[number];
|
|
4
4
|
/** How old a call may be before receivers reject it, so a captured call can't be replayed. */
|
|
5
5
|
declare const WEBHOOK_TOLERANCE_SECONDS: number;
|
|
@@ -24,8 +24,8 @@ declare function verifyWebhook(secret: string, headers: HeaderSource, body: stri
|
|
|
24
24
|
interface WebhookSettings {
|
|
25
25
|
url: string;
|
|
26
26
|
secret: string;
|
|
27
|
-
/**
|
|
28
|
-
events: ReadonlySet<string
|
|
27
|
+
/** The types that are sent (WEBHOOK_EVENTS); all others are skipped. */
|
|
28
|
+
events: ReadonlySet<string>;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export { type WebhookSettings as W, WEBHOOK_TOLERANCE_SECONDS as a, WEBHOOK_TYPES as b, type WebhookType as c, generateWebhookSecret as g, signWebhook as s, verifyWebhook as v };
|
package/dist/webhook.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { a as WEBHOOK_TOLERANCE_SECONDS, b as WEBHOOK_TYPES, c as WebhookType, g as generateWebhookSecret, s as signWebhook, v as verifyWebhook } from './webhook-
|
|
1
|
+
export { a as WEBHOOK_TOLERANCE_SECONDS, b as WEBHOOK_TYPES, c as WebhookType, g as generateWebhookSecret, s as signWebhook, v as verifyWebhook } from './webhook-ltwulgcB.js';
|
package/dist/webhook.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@madauth/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0-beta.2",
|
|
4
4
|
"description": "madAuth server: Google and e-mail & password sign-in with madAuth sessions, for Docker, AWS Lambda and Azure Functions.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "David Neuy",
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"jwt",
|
|
24
24
|
"hono",
|
|
25
25
|
"aws-lambda",
|
|
26
|
-
"azure-functions"
|
|
26
|
+
"azure-functions",
|
|
27
|
+
"dynamodb"
|
|
27
28
|
],
|
|
28
29
|
"type": "module",
|
|
29
30
|
"engines": {
|
|
@@ -44,6 +45,10 @@
|
|
|
44
45
|
"types": "./dist/store/sqlite.d.ts",
|
|
45
46
|
"import": "./dist/sqlite.js"
|
|
46
47
|
},
|
|
48
|
+
"./dynamodb": {
|
|
49
|
+
"types": "./dist/store/dynamodb.d.ts",
|
|
50
|
+
"import": "./dist/dynamodb.js"
|
|
51
|
+
},
|
|
47
52
|
"./testing": {
|
|
48
53
|
"types": "./dist/testing.d.ts",
|
|
49
54
|
"import": "./dist/testing.js"
|
|
@@ -87,14 +92,19 @@
|
|
|
87
92
|
"jose": "^6.2.12"
|
|
88
93
|
},
|
|
89
94
|
"peerDependencies": {
|
|
95
|
+
"@aws-sdk/client-dynamodb": "^3.0.0",
|
|
90
96
|
"@azure/functions": "^4.0.0"
|
|
91
97
|
},
|
|
92
98
|
"peerDependenciesMeta": {
|
|
99
|
+
"@aws-sdk/client-dynamodb": {
|
|
100
|
+
"optional": true
|
|
101
|
+
},
|
|
93
102
|
"@azure/functions": {
|
|
94
103
|
"optional": true
|
|
95
104
|
}
|
|
96
105
|
},
|
|
97
106
|
"devDependencies": {
|
|
107
|
+
"@aws-sdk/client-dynamodb": "^3.1146.0",
|
|
98
108
|
"@azure/functions": "^4.16.5",
|
|
99
109
|
"@types/aws-lambda": "^8.10.164",
|
|
100
110
|
"@types/node": "^26.6.4",
|