@adminforth/open-signup 2.0.3 → 2.0.5
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/.woodpecker/buildRelease.sh +3 -2
- package/build.log +0 -39
- package/dist/index.js +5 -7
- package/index.ts +9 -10
- package/package.json +4 -5
- package/tests/signupEmailCase.test.mjs +0 -113
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
#!/bin/bash
|
|
3
3
|
|
|
4
4
|
# write npm run output both to console and to build.log
|
|
5
|
-
npm
|
|
5
|
+
npm run build 2>&1 | tee build.log
|
|
6
6
|
build_status=${PIPESTATUS[0]}
|
|
7
7
|
|
|
8
|
-
# if
|
|
8
|
+
# if exist status from the npm run build is not 0
|
|
9
|
+
# then exit with the status code from the npm run build
|
|
9
10
|
if [ $build_status -ne 0 ]; then
|
|
10
11
|
echo "Build failed. Exiting with status code $build_status"
|
|
11
12
|
exit $build_status
|
package/build.log
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
> @adminforth/open-signup@1.0.9 test
|
|
3
|
-
> npm run build && node --test tests/*.test.mjs
|
|
4
|
-
|
|
5
|
-
|
|
6
2
|
> @adminforth/open-signup@1.0.9 build
|
|
7
3
|
> tsc && rsync -av --exclude 'node_modules' custom dist/
|
|
8
4
|
|
|
@@ -14,38 +10,3 @@ custom/tsconfig.json
|
|
|
14
10
|
|
|
15
11
|
sent 14,167 bytes received 77 bytes 28,488.00 bytes/sec
|
|
16
12
|
total size is 13,884 speedup is 0.97
|
|
17
|
-
TAP version 13
|
|
18
|
-
# Subtest: a case-variant signup is rejected instead of creating a second account
|
|
19
|
-
ok 1 - a case-variant signup is rejected instead of creating a second account
|
|
20
|
-
---
|
|
21
|
-
duration_ms: 45.208471
|
|
22
|
-
...
|
|
23
|
-
# Subtest: case folding does not depend on which column is the auth username field
|
|
24
|
-
ok 2 - case folding does not depend on which column is the auth username field
|
|
25
|
-
---
|
|
26
|
-
duration_ms: 43.686471
|
|
27
|
-
...
|
|
28
|
-
# Subtest: a configured column normalize runs on the folded value, and the stored value is the one probed
|
|
29
|
-
ok 3 - a configured column normalize runs on the folded value, and the stored value is the one probed
|
|
30
|
-
---
|
|
31
|
-
duration_ms: 48.158384
|
|
32
|
-
...
|
|
33
|
-
# Subtest: the probed value survives the column normalize core re-applies on write
|
|
34
|
-
ok 4 - the probed value survives the column normalize core re-applies on write
|
|
35
|
-
---
|
|
36
|
-
duration_ms: 41.121963
|
|
37
|
-
...
|
|
38
|
-
# Subtest: a login whose account lookup finds nothing returns an error instead of crashing
|
|
39
|
-
ok 5 - a login whose account lookup finds nothing returns an error instead of crashing
|
|
40
|
-
---
|
|
41
|
-
duration_ms: 0.192068
|
|
42
|
-
...
|
|
43
|
-
1..5
|
|
44
|
-
# tests 5
|
|
45
|
-
# suites 0
|
|
46
|
-
# pass 5
|
|
47
|
-
# fail 0
|
|
48
|
-
# cancelled 0
|
|
49
|
-
# skipped 0
|
|
50
|
-
# todo 0
|
|
51
|
-
# duration_ms 345.451587
|
package/dist/index.js
CHANGED
|
@@ -115,11 +115,12 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
|
|
|
115
115
|
const originList = Array.isArray(rawOrigins) ? rawOrigins : [rawOrigins];
|
|
116
116
|
return originList.map(o => new URL(o).origin);
|
|
117
117
|
}
|
|
118
|
-
// Unconditional fold: this value is both the lookup filter and the value stored.
|
|
119
118
|
normalizeUsername(email) {
|
|
120
|
-
|
|
119
|
+
if (this.adminforth.config.auth.usernameField !== this.emailField.name) {
|
|
120
|
+
return email;
|
|
121
|
+
}
|
|
121
122
|
const normalize = this.emailField.normalize;
|
|
122
|
-
return normalize ? normalize(
|
|
123
|
+
return normalize ? normalize(email) : email;
|
|
123
124
|
}
|
|
124
125
|
validateConfigAfterDiscover(adminforth, resourceConfig) {
|
|
125
126
|
if (this.options.confirmEmails) {
|
|
@@ -141,9 +142,6 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
|
|
|
141
142
|
return __awaiter(this, void 0, void 0, function* () {
|
|
142
143
|
const username = this.normalizeUsername(email);
|
|
143
144
|
const userRecord = yield this.adminforth.resource(this.authResource.resourceId).get(Filters.EQ(this.emailField.name, username));
|
|
144
|
-
if (!userRecord) {
|
|
145
|
-
return { allowedLogin: false, error: 'User not found' };
|
|
146
|
-
}
|
|
147
145
|
const adminUser = {
|
|
148
146
|
dbUser: userRecord,
|
|
149
147
|
pk: userRecord[this.authResource.columns.find((col) => col.primaryKey).name],
|
|
@@ -152,7 +150,7 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
|
|
|
152
150
|
const toReturn = { allowedLogin: true, error: '' };
|
|
153
151
|
yield this.adminforth.restApi.processLoginCallbacks(adminUser, toReturn, response, extra);
|
|
154
152
|
if (toReturn.allowedLogin) {
|
|
155
|
-
this.adminforth.auth.setAuthCookie({
|
|
153
|
+
yield this.adminforth.auth.setAuthCookie({
|
|
156
154
|
response,
|
|
157
155
|
username,
|
|
158
156
|
pk: userRecord[this.authResource.columns.find((col) => col.primaryKey).name]
|
package/index.ts
CHANGED
|
@@ -130,11 +130,13 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
|
|
|
130
130
|
return originList.map(o => new URL(o).origin);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
// Unconditional fold: this value is both the lookup filter and the value stored.
|
|
134
133
|
normalizeUsername(email: string): string {
|
|
135
|
-
|
|
134
|
+
if (this.adminforth.config.auth.usernameField !== this.emailField.name) {
|
|
135
|
+
return email;
|
|
136
|
+
}
|
|
137
|
+
|
|
136
138
|
const normalize = (this.emailField as AdminForthResourceColumn & { normalize?: (value: any) => any }).normalize;
|
|
137
|
-
return normalize ? normalize(
|
|
139
|
+
return normalize ? normalize(email) : email;
|
|
138
140
|
}
|
|
139
141
|
|
|
140
142
|
validateConfigAfterDiscover(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
|
|
@@ -160,10 +162,7 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
|
|
|
160
162
|
async doLogin(email: string, response: any, extra: HttpExtra): Promise<{ error?: string; allowedLogin: boolean; redirectTo?: string; }> {
|
|
161
163
|
const username = this.normalizeUsername(email);
|
|
162
164
|
const userRecord = await this.adminforth.resource(this.authResource.resourceId).get(Filters.EQ(this.emailField.name, username));
|
|
163
|
-
|
|
164
|
-
return { allowedLogin: false, error: 'User not found' };
|
|
165
|
-
}
|
|
166
|
-
const adminUser = {
|
|
165
|
+
const adminUser = {
|
|
167
166
|
dbUser: userRecord,
|
|
168
167
|
pk: userRecord[this.authResource.columns.find((col) => col.primaryKey).name],
|
|
169
168
|
username,
|
|
@@ -172,9 +171,9 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
|
|
|
172
171
|
|
|
173
172
|
await this.adminforth.restApi.processLoginCallbacks(adminUser, toReturn, response, extra);
|
|
174
173
|
if (toReturn.allowedLogin) {
|
|
175
|
-
this.adminforth.auth.setAuthCookie({
|
|
176
|
-
response,
|
|
177
|
-
username,
|
|
174
|
+
await this.adminforth.auth.setAuthCookie({
|
|
175
|
+
response,
|
|
176
|
+
username,
|
|
178
177
|
pk: userRecord[
|
|
179
178
|
this.authResource.columns.find((col) => col.primaryKey).name
|
|
180
179
|
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adminforth/open-signup",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"homepage": "https://adminforth.dev/docs/tutorial/Plugins/open-signup/",
|
|
11
11
|
"scripts": {
|
|
12
|
-
"build": "tsc && rsync -av --exclude 'node_modules' custom dist/"
|
|
13
|
-
"test": "npm run build && node --test tests/*.test.mjs"
|
|
12
|
+
"build": "tsc && rsync -av --exclude 'node_modules' custom dist/"
|
|
14
13
|
},
|
|
15
14
|
"repository": {
|
|
16
15
|
"type": "git",
|
|
@@ -28,11 +27,11 @@
|
|
|
28
27
|
"zod": "^4.3.6"
|
|
29
28
|
},
|
|
30
29
|
"peerDependencies": {
|
|
31
|
-
"adminforth": "^3.
|
|
30
|
+
"adminforth": "^3.31.5"
|
|
32
31
|
},
|
|
33
32
|
"devDependencies": {
|
|
34
33
|
"@types/node": "^22.10.7",
|
|
35
|
-
"adminforth": "^3.
|
|
34
|
+
"adminforth": "^3.31.5",
|
|
36
35
|
"semantic-release": "^24.2.1",
|
|
37
36
|
"semantic-release-slack-bot": "^4.0.2",
|
|
38
37
|
"typescript": "^5.7.3"
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import test from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import OpenSignupPlugin from '../dist/index.js';
|
|
4
|
-
|
|
5
|
-
function makePlugin({ usernameField = 'email', normalize } = {}) {
|
|
6
|
-
const records = [];
|
|
7
|
-
const cookies = [];
|
|
8
|
-
const plugin = Object.create(OpenSignupPlugin.prototype);
|
|
9
|
-
|
|
10
|
-
plugin.options = {
|
|
11
|
-
emailField: 'email',
|
|
12
|
-
passwordHashField: 'password_hash',
|
|
13
|
-
expectedOrigin: 'https://app.example.com',
|
|
14
|
-
};
|
|
15
|
-
plugin.pluginInstanceId = 'open-signup-test';
|
|
16
|
-
plugin.emailField = { name: 'email', ...(normalize ? { normalize } : {}) };
|
|
17
|
-
plugin.passwordField = { minLength: 8, maxLength: 64 };
|
|
18
|
-
plugin.authResource = {
|
|
19
|
-
resourceId: 'users',
|
|
20
|
-
columns: [{ name: 'id', primaryKey: true }, { name: 'email' }],
|
|
21
|
-
};
|
|
22
|
-
plugin.adminforth = {
|
|
23
|
-
config: { auth: { usernameField }, customization: { brandName: 'Test' } },
|
|
24
|
-
resource: () => ({
|
|
25
|
-
get: async (filter) => records.find((record) => record.email === filter.value) ?? null,
|
|
26
|
-
create: async (record) => {
|
|
27
|
-
// core applies the column's normalize again on write, so the harness has to as well
|
|
28
|
-
const email = normalize ? normalize(record.email) : record.email;
|
|
29
|
-
const created = { id: `user-${records.length + 1}`, ...record, email };
|
|
30
|
-
records.push(created);
|
|
31
|
-
return created;
|
|
32
|
-
},
|
|
33
|
-
}),
|
|
34
|
-
restApi: { processLoginCallbacks: async () => {} },
|
|
35
|
-
auth: { setAuthCookie: (args) => cookies.push(args) },
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
let handler;
|
|
39
|
-
plugin.setupEndpoints({
|
|
40
|
-
endpoint: (options) => {
|
|
41
|
-
if (options.path.endsWith('/signup')) {
|
|
42
|
-
handler = options.handler;
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const signup = (email) => handler({
|
|
48
|
-
body: { email, url: 'https://app.example.com/signup', password: 'S3cret-pass' },
|
|
49
|
-
response: {},
|
|
50
|
-
headers: {},
|
|
51
|
-
query: {},
|
|
52
|
-
cookies: [],
|
|
53
|
-
requestUrl: '/plugin/open-signup-test/signup',
|
|
54
|
-
tr: async (message) => message,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
return { plugin, records, cookies, signup };
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
test('a case-variant signup is rejected instead of creating a second account', async () => {
|
|
61
|
-
const { records, signup, cookies } = makePlugin();
|
|
62
|
-
|
|
63
|
-
// the first address is deliberately mixed-case: it is what pins the stored value to the folded one
|
|
64
|
-
const first = await signup('Bob@Example.COM');
|
|
65
|
-
assert.equal(first.allowedLogin, true);
|
|
66
|
-
assert.equal(records.length, 1);
|
|
67
|
-
assert.equal(records[0].email, 'bob@example.com');
|
|
68
|
-
assert.equal(cookies.at(-1).username, 'bob@example.com');
|
|
69
|
-
|
|
70
|
-
const second = await signup('bob@example.com');
|
|
71
|
-
assert.match(second.error, /already exists/i);
|
|
72
|
-
assert.equal(records.length, 1);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test('case folding does not depend on which column is the auth username field', async () => {
|
|
76
|
-
const { records, signup } = makePlugin({ usernameField: 'login' });
|
|
77
|
-
|
|
78
|
-
await signup('bob@example.com');
|
|
79
|
-
const second = await signup('BOB@example.com');
|
|
80
|
-
|
|
81
|
-
assert.match(second.error, /already exists/i);
|
|
82
|
-
assert.equal(records.length, 1);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test('a configured column normalize runs on the folded value, and the stored value is the one probed', async () => {
|
|
86
|
-
const { records, signup } = makePlugin({ normalize: (value) => value.trim() });
|
|
87
|
-
|
|
88
|
-
await signup(' bob@example.com ');
|
|
89
|
-
const second = await signup('Bob@Example.com');
|
|
90
|
-
|
|
91
|
-
assert.match(second.error, /already exists/i);
|
|
92
|
-
assert.equal(records.length, 1);
|
|
93
|
-
assert.equal(records[0].email, 'bob@example.com');
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test('the probed value survives the column normalize core re-applies on write', async () => {
|
|
97
|
-
const { records, signup } = makePlugin({ normalize: (value) => value.toUpperCase() });
|
|
98
|
-
|
|
99
|
-
await signup('bob@example.com');
|
|
100
|
-
const second = await signup('Bob@Example.com');
|
|
101
|
-
|
|
102
|
-
assert.match(second.error, /already exists/i);
|
|
103
|
-
assert.equal(records.length, 1);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
test('a login whose account lookup finds nothing returns an error instead of crashing', async () => {
|
|
107
|
-
const { plugin } = makePlugin();
|
|
108
|
-
|
|
109
|
-
const result = await plugin.doLogin('nobody@example.com', {}, {});
|
|
110
|
-
|
|
111
|
-
assert.equal(result.allowedLogin, false);
|
|
112
|
-
assert.match(result.error, /not found/i);
|
|
113
|
-
});
|