@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.
@@ -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 test 2>&1 | tee build.log
5
+ npm run build 2>&1 | tee build.log
6
6
  build_status=${PIPESTATUS[0]}
7
7
 
8
- # if exit status is not 0, exit with the status code from the build+test run
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
- const folded = typeof email === 'string' ? email.toLowerCase() : email;
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(folded) : folded;
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
- const folded = typeof email === 'string' ? email.toLowerCase() : email;
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(folded) : folded;
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
- if (!userRecord) {
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",
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.8.2"
30
+ "adminforth": "^3.31.5"
32
31
  },
33
32
  "devDependencies": {
34
33
  "@types/node": "^22.10.7",
35
- "adminforth": "^3.8.2",
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
- });