@adminforth/open-signup 1.3.0 → 2.0.0

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/build.log CHANGED
@@ -8,5 +8,5 @@ custom/SignupPage.vue
8
8
  custom/SignupUnderLogin.vue
9
9
  custom/tsconfig.json
10
10
 
11
- sent 14,167 bytes received 77 bytes 28,488.00 bytes/sec
11
+ sent 14,163 bytes received 77 bytes 28,480.00 bytes/sec
12
12
  total size is 13,884 speedup is 0.97
package/dist/index.d.ts CHANGED
@@ -10,6 +10,7 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
10
10
  adminforth: IAdminForth;
11
11
  constructor(options: PluginOptions);
12
12
  modifyResourceConfig(adminforth: IAdminForth, resourceConfig: AdminForthResource): Promise<void>;
13
+ getAllowedOrigins(): string[];
13
14
  validateConfigAfterDiscover(adminforth: IAdminForth, resourceConfig: AdminForthResource): void;
14
15
  instanceUniqueRepresentation(pluginOptions: any): string;
15
16
  doLogin(email: string, response: any, extra: HttpExtra): Promise<{
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import AdminForth, { AdminForthPlugin, parseBody, Filters, suggestIfTypo, AdminForthDataTypes } from "adminforth";
10
+ import AdminForth, { AdminForthPlugin, Filters, suggestIfTypo, AdminForthDataTypes } from "adminforth";
11
11
  import { z } from "zod";
12
12
  const completeVerifiedSignupBodySchema = z.object({
13
13
  token: z.string(),
@@ -94,8 +94,27 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
94
94
  adminforth.config.auth.beforeLoginConfirmation = [];
95
95
  }
96
96
  }
97
+ const rawOrigins = this.options.expectedOrigin;
98
+ const originList = Array.isArray(rawOrigins) ? rawOrigins : [rawOrigins];
99
+ if (!rawOrigins || originList.length === 0 || originList.some(o => !o)) {
100
+ throw new Error('EmailPasswordReset: expectedOrigin is required. Set it to the admin panel origin(s) ' +
101
+ '(e.g. "https://admin.example.com") so reset links can only point to a trusted host.');
102
+ }
103
+ for (const origin of originList) {
104
+ try {
105
+ new URL(origin);
106
+ }
107
+ catch (_a) {
108
+ throw new Error(`EmailPasswordReset: expectedOrigin "${origin}" is not a valid absolute URL/origin.`);
109
+ }
110
+ }
97
111
  });
98
112
  }
113
+ getAllowedOrigins() {
114
+ const rawOrigins = this.options.expectedOrigin;
115
+ const originList = Array.isArray(rawOrigins) ? rawOrigins : [rawOrigins];
116
+ return originList.map(o => new URL(o).origin);
117
+ }
99
118
  validateConfigAfterDiscover(adminforth, resourceConfig) {
100
119
  if (this.options.confirmEmails) {
101
120
  this.options.confirmEmails.adapter.validate();
@@ -159,11 +178,9 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
159
178
  method: 'POST',
160
179
  path: `/plugin/${this.pluginInstanceId}/complete-verified-signup`,
161
180
  noAuth: true,
181
+ request_schema: completeVerifiedSignupBodySchema,
162
182
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, response, headers, query, cookies, tr, requestUrl }) {
163
- const parsed = parseBody(completeVerifiedSignupBodySchema, body, response);
164
- if ('error' in parsed)
165
- return parsed.error;
166
- const data = parsed.data;
183
+ const data = body;
167
184
  const { token, password } = data;
168
185
  if (!token) {
169
186
  return { error: yield tr('Invalid token', 'opensignup'), ok: false };
@@ -194,12 +211,10 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
194
211
  method: 'POST',
195
212
  path: `/plugin/${this.pluginInstanceId}/signup`,
196
213
  noAuth: true,
214
+ request_schema: signupBodySchema,
197
215
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, response, headers, query, cookies, tr, requestUrl }) {
198
216
  var _b, _c;
199
- const parsed = parseBody(signupBodySchema, body, response);
200
- if ('error' in parsed)
201
- return parsed.error;
202
- const data = parsed.data;
217
+ const data = body;
203
218
  const { email, url, password } = data;
204
219
  if (!email || typeof email !== 'string') {
205
220
  return { error: yield tr('Email is required', 'opensignup'), ok: false };
@@ -207,6 +222,18 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
207
222
  if (!this.options.confirmEmails && !password) {
208
223
  return { error: yield tr('Password is required', 'opensignup'), ok: false };
209
224
  }
225
+ let resetLink;
226
+ try {
227
+ const parsedUrl = new URL(url);
228
+ if (!this.getAllowedOrigins().includes(parsedUrl.origin)) {
229
+ return { error: 'Invalid reset url', ok: false };
230
+ }
231
+ parsedUrl.hash = '';
232
+ resetLink = parsedUrl.toString();
233
+ }
234
+ catch (_d) {
235
+ return { error: 'Invalid reset url', ok: false };
236
+ }
210
237
  const extra = { body, headers, query, cookies, requestUrl: url };
211
238
  // validate email
212
239
  if (this.emailField.validation) {
package/dist/types.d.ts CHANGED
@@ -54,4 +54,9 @@ export interface PluginOptions extends PluginsCommonOptions {
54
54
  * Signup component order inder login button
55
55
  */
56
56
  loginPageComponentOrder?: number;
57
+ /**
58
+ * The origin(s) (scheme + host + optional port) of the admin panel that are
59
+ * allowed to appear in password reset links, e.g. "https://admin.example.com".
60
+ */
61
+ expectedOrigin: string | string[];
57
62
  }
package/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import AdminForth, { AdminForthPlugin, parseBody, Filters, suggestIfTypo, AdminForthDataTypes } from "adminforth";
1
+ import AdminForth, { AdminForthPlugin, Filters, suggestIfTypo, AdminForthDataTypes } from "adminforth";
2
2
  import type { IAdminForth, IHttpServer, AdminForthComponentDeclaration, AdminForthResourceColumn, AdminForthResource, BeforeLoginConfirmationFunction, HttpExtra } from "adminforth";
3
3
  import type { PluginOptions } from './types.js';
4
4
  import { z } from "zod";
@@ -106,6 +106,28 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
106
106
  adminforth.config.auth.beforeLoginConfirmation = [];
107
107
  }
108
108
  }
109
+
110
+ const rawOrigins = this.options.expectedOrigin;
111
+ const originList = Array.isArray(rawOrigins) ? rawOrigins : [rawOrigins];
112
+ if (!rawOrigins || originList.length === 0 || originList.some(o => !o)) {
113
+ throw new Error(
114
+ 'EmailPasswordReset: expectedOrigin is required. Set it to the admin panel origin(s) ' +
115
+ '(e.g. "https://admin.example.com") so reset links can only point to a trusted host.'
116
+ );
117
+ }
118
+ for (const origin of originList) {
119
+ try {
120
+ new URL(origin);
121
+ } catch {
122
+ throw new Error(`EmailPasswordReset: expectedOrigin "${origin}" is not a valid absolute URL/origin.`);
123
+ }
124
+ }
125
+ }
126
+
127
+ getAllowedOrigins(): string[] {
128
+ const rawOrigins = this.options.expectedOrigin;
129
+ const originList = Array.isArray(rawOrigins) ? rawOrigins : [rawOrigins];
130
+ return originList.map(o => new URL(o).origin);
109
131
  }
110
132
 
111
133
  validateConfigAfterDiscover(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
@@ -185,10 +207,9 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
185
207
  method: 'POST',
186
208
  path: `/plugin/${this.pluginInstanceId}/complete-verified-signup`,
187
209
  noAuth: true,
210
+ request_schema: completeVerifiedSignupBodySchema,
188
211
  handler: async ({ body, response, headers, query, cookies, tr, requestUrl }) => {
189
- const parsed = parseBody(completeVerifiedSignupBodySchema, body, response);
190
- if ('error' in parsed) return parsed.error;
191
- const data = parsed.data;
212
+ const data = body as z.infer<typeof completeVerifiedSignupBodySchema>;
192
213
  const { token, password } = data;
193
214
  if (!token) {
194
215
  return { error: await tr('Invalid token', 'opensignup'), ok: false };
@@ -223,10 +244,9 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
223
244
  method: 'POST',
224
245
  path: `/plugin/${this.pluginInstanceId}/signup`,
225
246
  noAuth: true,
247
+ request_schema: signupBodySchema,
226
248
  handler: async ({ body, response, headers, query, cookies, tr, requestUrl }) => {
227
- const parsed = parseBody(signupBodySchema, body, response);
228
- if ('error' in parsed) return parsed.error;
229
- const data = parsed.data;
249
+ const data = body as z.infer<typeof signupBodySchema>;
230
250
  const { email, url, password } = data;
231
251
  if (!email || typeof email !== 'string') {
232
252
  return { error: await tr('Email is required', 'opensignup'), ok: false };
@@ -234,6 +254,19 @@ export default class OpenSignupPlugin extends AdminForthPlugin {
234
254
  if (!this.options.confirmEmails && !password) {
235
255
  return { error: await tr('Password is required', 'opensignup'), ok: false };
236
256
  }
257
+
258
+ let resetLink: string;
259
+ try {
260
+ const parsedUrl = new URL(url);
261
+ if (!this.getAllowedOrigins().includes(parsedUrl.origin)) {
262
+ return { error: 'Invalid reset url', ok: false };
263
+ }
264
+ parsedUrl.hash = '';
265
+ resetLink = parsedUrl.toString();
266
+ } catch {
267
+ return { error: 'Invalid reset url', ok: false };
268
+ }
269
+
237
270
  const extra = { body, headers, query, cookies, requestUrl: url };
238
271
  // validate email
239
272
  if (this.emailField.validation) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/open-signup",
3
- "version": "1.3.0",
3
+ "version": "2.0.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -27,11 +27,11 @@
27
27
  "zod": "^4.3.6"
28
28
  },
29
29
  "peerDependencies": {
30
- "adminforth": "^3.7.1"
30
+ "adminforth": "^3.8.2"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^22.10.7",
34
- "adminforth": "^3.7.1",
34
+ "adminforth": "^3.8.2",
35
35
  "semantic-release": "^24.2.1",
36
36
  "semantic-release-slack-bot": "^4.0.2",
37
37
  "typescript": "^5.7.3"
package/types.ts CHANGED
@@ -70,4 +70,11 @@ export interface PluginOptions extends PluginsCommonOptions {
70
70
  * Signup component order inder login button
71
71
  */
72
72
  loginPageComponentOrder?: number;
73
+
74
+ /**
75
+ * The origin(s) (scheme + host + optional port) of the admin panel that are
76
+ * allowed to appear in password reset links, e.g. "https://admin.example.com".
77
+ */
78
+ expectedOrigin: string | string[];
79
+
73
80
  }