firstly 0.0.5 → 0.0.7

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 (42) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/esm/ROUTES.d.ts +13 -11
  3. package/esm/ROUTES.js +6 -5
  4. package/esm/api/index.d.ts +1 -1
  5. package/esm/auth/Adapter.js +4 -2
  6. package/esm/auth/AuthController.server.js +129 -66
  7. package/esm/auth/Entities.d.ts +1 -1
  8. package/esm/auth/Entities.js +3 -3
  9. package/esm/auth/RoleHelpers.js +8 -8
  10. package/esm/auth/client/Auth.js +1 -1
  11. package/esm/auth/index.d.ts +4 -7
  12. package/esm/auth/index.js +41 -36
  13. package/esm/auth/static/assets/Page-BGTO8LC5.css +1 -0
  14. package/esm/auth/static/assets/Page-DBWJjlEQ.d.ts +4 -0
  15. package/esm/auth/static/assets/Page-DBWJjlEQ.js +1 -0
  16. package/esm/auth/static/assets/Page-RIbXHuZG.d.ts +4 -0
  17. package/esm/auth/static/assets/Page-RIbXHuZG.js +1 -0
  18. package/esm/auth/static/assets/Page-apb_xgZT.d.ts +6 -0
  19. package/esm/auth/static/assets/Page-apb_xgZT.js +18 -0
  20. package/esm/auth/static/assets/{index-R27C_TlP.css → index-CR_3yNaJ.css} +1 -1
  21. package/esm/auth/static/assets/index-qfq98Nyd.d.ts +63 -0
  22. package/esm/auth/static/assets/index-qfq98Nyd.js +2 -0
  23. package/esm/auth/static/index.html +2 -2
  24. package/esm/auth/types.d.ts +16 -22
  25. package/esm/cellsBuildor.js +2 -2
  26. package/esm/index.d.ts +3 -2
  27. package/esm/index.js +2 -1
  28. package/esm/mail/index.d.ts +23 -4
  29. package/esm/mail/index.js +38 -15
  30. package/esm/mail/templates/DefaultMail.svelte +66 -0
  31. package/esm/mail/templates/DefaultMail.svelte.d.ts +28 -0
  32. package/esm/utils/types.d.ts +3 -0
  33. package/package.json +2 -1
  34. package/esm/auth/static/assets/Page-BYzkK4q3.d.ts +0 -5
  35. package/esm/auth/static/assets/Page-BYzkK4q3.js +0 -1
  36. package/esm/auth/static/assets/Page-ByIhtXVt.d.ts +0 -5
  37. package/esm/auth/static/assets/Page-ByIhtXVt.js +0 -8190
  38. package/esm/auth/static/assets/Page-Do7F0Mzd.d.ts +0 -5
  39. package/esm/auth/static/assets/Page-Do7F0Mzd.js +0 -1
  40. package/esm/auth/static/assets/Page-gV58jf2r.css +0 -1
  41. package/esm/auth/static/assets/index-czJ1PA1n.d.ts +0 -53
  42. package/esm/auth/static/assets/index-czJ1PA1n.js +0 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # firstly
2
2
 
3
+ ## 0.0.7
4
+
5
+ ### Patch Changes
6
+
7
+ - [#25](https://github.com/jycouet/firstly/pull/25)
8
+ [`54f2f6a`](https://github.com/jycouet/firstly/commit/54f2f6a833c1977c3163e91ce3172fa8edc9da47)
9
+ Thanks [@jycouet](https://github.com/jycouet)! - adding e2e tests for accounts
10
+
11
+ - [#25](https://github.com/jycouet/firstly/pull/25)
12
+ [`943e9d0`](https://github.com/jycouet/firstly/commit/943e9d0b6d5d6a631dc78661d188a76f254d4632)
13
+ Thanks [@jycouet](https://github.com/jycouet)! - rename name to identifier in db
14
+
15
+ ## 0.0.6
16
+
17
+ ### Patch Changes
18
+
19
+ - [#23](https://github.com/jycouet/firstly/pull/23)
20
+ [`c188eb3`](https://github.com/jycouet/firstly/commit/c188eb3d81a9e75b246387512621b5213bbe8dbd)
21
+ Thanks [@jycouet](https://github.com/jycouet)! - fix auth & mail (logs & co)
22
+
3
23
  ## 0.0.5
4
24
 
5
25
  ### Patch Changes
package/esm/ROUTES.d.ts CHANGED
@@ -32,15 +32,16 @@ declare const AllObjs: {
32
32
  repo?: (string | number);
33
33
  }) => string;
34
34
  "/": string;
35
- "/remult": string;
36
- "/remult/auth": string;
37
- "/remult/enum": string;
38
- "/remult/select": string;
39
- "/ui": string;
35
+ "/auth": string;
36
+ "/mail": string;
37
+ "/ui/dialog": string;
38
+ "/ui/enum": string;
39
+ "/ui/fieldGroup": string;
40
+ "/ui/select": string;
40
41
  };
41
42
  type AllTypes = typeof AllObjs;
42
43
  export type Routes = keyof AllTypes extends `${string}/${infer Route}` ? `/${Route}` : keyof AllTypes;
43
- export declare const routes: ("/" | "/remult" | "/remult/auth" | "/remult/enum" | "/remult/select" | "/ui" | "firstly_sign_in" | "remult_admin" | "github")[];
44
+ export declare const routes: ("/" | "/auth" | "/mail" | "/ui/dialog" | "/ui/enum" | "/ui/fieldGroup" | "/ui/select" | "firstly_sign_in" | "remult_admin" | "github")[];
44
45
  /**
45
46
  * To be used like this:
46
47
  * ```ts
@@ -69,11 +70,12 @@ export declare function route<T extends NonFunctionKeys<AllTypes>>(key: T): stri
69
70
  export type KIT_ROUTES = {
70
71
  PAGES: {
71
72
  '/': never;
72
- '/remult': never;
73
- '/remult/auth': never;
74
- '/remult/enum': never;
75
- '/remult/select': never;
76
- '/ui': never;
73
+ '/auth': never;
74
+ '/mail': never;
75
+ '/ui/dialog': never;
76
+ '/ui/enum': never;
77
+ '/ui/fieldGroup': never;
78
+ '/ui/select': never;
77
79
  };
78
80
  SERVERS: Record<string, never>;
79
81
  ACTIONS: Record<string, never>;
package/esm/ROUTES.js CHANGED
@@ -9,11 +9,12 @@
9
9
  */
10
10
  const PAGES = {
11
11
  "/": `/`,
12
- "/remult": `/remult`,
13
- "/remult/auth": `/remult/auth`,
14
- "/remult/enum": `/remult/enum`,
15
- "/remult/select": `/remult/select`,
16
- "/ui": `/ui`
12
+ "/auth": `/auth`,
13
+ "/mail": `/mail`,
14
+ "/ui/dialog": `/ui/dialog`,
15
+ "/ui/enum": `/ui/enum`,
16
+ "/ui/fieldGroup": `/ui/fieldGroup`,
17
+ "/ui/select": `/ui/select`
17
18
  };
18
19
  /**
19
20
  * SERVERS
@@ -26,7 +26,7 @@ export type Module = {
26
26
  };
27
27
  type Options = Omit<RemultServerOptions<RequestEvent<Partial<Record<string, string>>, string | null>> & {
28
28
  modules?: Module[] | undefined;
29
- mail?: MailOptions;
29
+ mail?: MailOptions<any>;
30
30
  }, 'entities' | 'controllers' | 'initRequest' | 'initApi'>;
31
31
  /**
32
32
  * it's basically `remultSveltekit` with the `modules` option
@@ -7,12 +7,14 @@ export class RemultLuciaAdapter {
7
7
  if (session) {
8
8
  const user = await remult.repo(oSafe.User).findId(session.userId);
9
9
  if (user) {
10
+ const { identifier, ...userInfo } = user;
10
11
  return [
11
12
  { ...session, attributes: {} },
12
13
  {
13
- ...user,
14
+ ...userInfo,
14
15
  attributes: {
15
- ...user,
16
+ ...userInfo,
17
+ name: identifier,
16
18
  session: { id: session.id, expiresAt: session.expiresAt },
17
19
  },
18
20
  },
@@ -3,7 +3,7 @@ import { DEV } from 'esm-env';
3
3
  import { generateId } from 'lucia';
4
4
  import { createDate, TimeSpan } from 'oslo';
5
5
  import { remult } from 'remult';
6
- import { green, yellow } from '@kitql/helpers';
6
+ import { green, magenta, yellow } from '@kitql/helpers';
7
7
  import { AUTH_OPTIONS, getSafeOptions, logAuth, lucia } from '.';
8
8
  import { sendMail } from '../mail';
9
9
  import { FFAuthProvider } from './Entities.js';
@@ -58,11 +58,11 @@ export class AuthControllerServer {
58
58
  throw new Error(`${name} not found as demo account!`);
59
59
  }
60
60
  const oSafe = getSafeOptions();
61
- let user = await remult.repo(oSafe.User).findFirst({ name });
61
+ let user = await remult.repo(oSafe.User).findFirst({ identifier: name });
62
62
  if (!user) {
63
63
  user = remult.repo(oSafe.User).create();
64
64
  }
65
- user.name = name;
65
+ user.identifier = name;
66
66
  const r = mergeRoles(user.roles, account.roles);
67
67
  user.roles = r.roles;
68
68
  await remult.repo(oSafe.User).save(user);
@@ -75,28 +75,55 @@ export class AuthControllerServer {
75
75
  */
76
76
  static async invite(email) {
77
77
  const oSafe = getSafeOptions();
78
- const existingUser = await remult.repo(oSafe.User).findOne({ where: { name: email } });
79
- if (existingUser) {
78
+ const existingAccount = await remult.repo(oSafe.Account).findOne({
79
+ where: {
80
+ providerUserId: email,
81
+ provider: FFAuthProvider.PASSWORD.id,
82
+ },
83
+ });
84
+ if (existingAccount) {
80
85
  // throw Error("Already invited !")
81
86
  }
82
87
  else {
83
- const user = await remult.repo(oSafe.User).insert({
84
- name: email,
88
+ const token = generateId(40);
89
+ await remult.repo(oSafe.Account).insert({
90
+ provider: FFAuthProvider.PASSWORD.id,
91
+ providerUserId: email,
92
+ // userId: user.id,
93
+ // hashPassword: await passwordHash(password),
94
+ token: oSafe.verifiedMethod === 'auto' ? undefined : token,
95
+ expiresAt: createDate(new TimeSpan(AUTH_OPTIONS.providers?.password?.verifyMailExpiresIn ?? 5 * 60, 's')),
96
+ lastVerifiedAt: undefined,
85
97
  });
86
- const url = `${remult.context.url.origin}`;
98
+ const url = `${remult.context.url.origin}${oSafe.firstlyData.props.ui?.paths.verify_email}?token=${token}`;
87
99
  if (AUTH_OPTIONS?.invitationSend) {
88
100
  await AUTH_OPTIONS?.invitationSend({ email, url });
89
- logAuth.success(`Done with custom ${green('invitationSend')} (${yellow(url)})`);
101
+ logAuth.success(`${green('[custom]')}${magenta('[invitationSend]')} (${yellow(url)})`);
90
102
  return 'Mail sent !';
91
103
  }
92
104
  else {
93
- await sendMail('invite', {
105
+ await sendMail('invitationSend', {
94
106
  to: email,
95
107
  subject: 'Invitation',
96
- text: `You were invited here: ${url}`,
97
- html: `You were invited <a href="${url}">here</a>`,
108
+ templateProps: {
109
+ title: 'Invitation 👋',
110
+ previewText: 'This is the mail you were waiting for',
111
+ sections: [
112
+ {
113
+ text: 'Today is your lucky day !',
114
+ highlighted: true,
115
+ },
116
+ {
117
+ text: 'You were invited to join the team',
118
+ cta: {
119
+ text: 'JOIN',
120
+ link: url,
121
+ },
122
+ },
123
+ ],
124
+ },
98
125
  });
99
- logAuth.success(`Done with ${green('sendMail')} (${url})`);
126
+ logAuth.success(`${magenta('[invitationSend]')} (${yellow(url)})`);
100
127
  return 'Demo Mail sent !';
101
128
  }
102
129
  }
@@ -114,43 +141,66 @@ export class AuthControllerServer {
114
141
  if (!oSafe.password_enabled) {
115
142
  throw Error('Password is not enabled!');
116
143
  }
117
- const existingUser = await remult.repo(oSafe.User).findOne({ where: { name: email } });
118
- if (existingUser) {
144
+ const existingAccount = await remult.repo(oSafe.Account).findOne({
145
+ where: {
146
+ providerUserId: email,
147
+ provider: FFAuthProvider.PASSWORD.id,
148
+ },
149
+ });
150
+ if (existingAccount) {
119
151
  throw Error("You can't signup twice !");
120
152
  }
121
153
  checkPassword(password);
122
- const user = await remult.repo(oSafe.User).insert({
123
- name: email,
124
- });
125
154
  const token = generateId(40);
126
- await remult.repo(oSafe.Account).insert({
127
- provider: FFAuthProvider.PASSWORD.id,
128
- providerUserId: email,
129
- userId: user.id,
130
- hashPassword: await passwordHash(password),
131
- token: oSafe.verifiedMethod === 'auto' ? undefined : token,
132
- expiresAt: oSafe.verifiedMethod === 'auto'
133
- ? undefined
134
- : createDate(new TimeSpan(AUTH_OPTIONS.providers?.password?.verifyMailExpiresIn ?? 5 * 60, 's')),
135
- lastVerifiedAt: oSafe.verifiedMethod === 'auto' ? new Date() : undefined,
155
+ await remult.dataProvider.transaction(async () => {
156
+ const user = await remult.repo(oSafe.User).insert({
157
+ identifier: email,
158
+ });
159
+ await remult.repo(oSafe.Account).insert({
160
+ provider: FFAuthProvider.PASSWORD.id,
161
+ providerUserId: email,
162
+ userId: user.id,
163
+ hashPassword: await passwordHash(password),
164
+ token: oSafe.verifiedMethod === 'auto' ? undefined : token,
165
+ expiresAt: oSafe.verifiedMethod === 'auto'
166
+ ? undefined
167
+ : createDate(new TimeSpan(AUTH_OPTIONS.providers?.password?.verifyMailExpiresIn ?? 5 * 60, 's')),
168
+ lastVerifiedAt: oSafe.verifiedMethod === 'auto' ? new Date() : undefined,
169
+ });
136
170
  });
137
171
  if (oSafe.verifiedMethod === 'auto') {
138
- await createSession(user.id);
172
+ const user = await remult.repo(oSafe.User).findFirst({
173
+ identifier: email,
174
+ });
175
+ if (user) {
176
+ await createSession(user.id);
177
+ }
139
178
  }
140
179
  else {
141
- const url = `${remult.context.url.origin}${oSafe.firstlyData.props.ui.providers.password.paths.verify_email}?token=${token}`;
180
+ const url = `${remult.context.url.origin}${oSafe.firstlyData.props.ui?.paths.verify_email}?token=${token}`;
142
181
  if (AUTH_OPTIONS.providers?.password?.verifyMailSend) {
143
182
  await AUTH_OPTIONS.providers?.password.verifyMailSend({ email, url });
144
- logAuth.success(`Done with custom ${green('verifyMailSend')} (${yellow(url)})`);
183
+ logAuth.success(`${green('[custom]')}${magenta('[verifyMailSend]')} (${yellow(url)})`);
145
184
  }
146
185
  else {
147
- await sendMail('signUpPassword', {
186
+ await sendMail('verifyMailSend', {
148
187
  to: email,
149
- subject: 'Wecome!',
150
- text: `You can validate your account here: ${url}`,
151
- html: `You can validate your account <a href="${url}">here</a>`,
188
+ subject: 'Wecome',
189
+ templateProps: {
190
+ title: 'Wecome 👋',
191
+ previewText: 'This is the mail you were waiting for',
192
+ sections: [
193
+ {
194
+ text: 'You can validate your account',
195
+ cta: {
196
+ text: 'HERE',
197
+ link: url,
198
+ },
199
+ },
200
+ ],
201
+ },
152
202
  });
153
- logAuth.success(`Done with ${green('sendMail')} (${url})`);
203
+ logAuth.success(`${magenta('[verifyMailSend]')} (${yellow(url)})`);
154
204
  }
155
205
  }
156
206
  return 'ok';
@@ -164,14 +214,16 @@ export class AuthControllerServer {
164
214
  if (!oSafe.password_enabled) {
165
215
  throw Error('Password is not enabled!');
166
216
  }
167
- const existingUser = await remult
168
- .repo(oSafe.User)
169
- .findOne({ where: { name: email }, include: { accounts: true } });
170
- const accountPassword = existingUser?.accounts.find((c) => c.provider === FFAuthProvider.PASSWORD.id);
171
- if (accountPassword && existingUser) {
172
- const validPassword = await passwordVerify(accountPassword?.hashPassword ?? '', password ?? '');
217
+ const existingAccount = await remult.repo(oSafe.Account).findOne({
218
+ where: {
219
+ providerUserId: email,
220
+ provider: FFAuthProvider.PASSWORD.id,
221
+ },
222
+ });
223
+ if (existingAccount) {
224
+ const validPassword = await passwordVerify(existingAccount?.hashPassword ?? '', password ?? '');
173
225
  if (validPassword) {
174
- await createSession(existingUser.id);
226
+ await createSession(existingAccount.userId);
175
227
  return 'ok';
176
228
  }
177
229
  throw Error('Incorrect username or password');
@@ -186,35 +238,46 @@ export class AuthControllerServer {
186
238
  if (!oSafe.password_enabled) {
187
239
  throw Error('Password is not enabled!');
188
240
  }
189
- const u = await remult.repo(getSafeOptions().User).findFirst({ name: email });
190
- if (u) {
191
- let authAccount = await remult.repo(oSafe.Account).findFirst({
192
- userId: u.id,
193
- });
194
- if (!authAccount) {
195
- authAccount = remult.repo(oSafe.Account).create();
196
- authAccount.userId = u.id;
197
- authAccount.provider = FFAuthProvider.PASSWORD.id;
198
- authAccount.providerUserId = email;
199
- }
241
+ const existingAccount = await remult.repo(oSafe.Account).findOne({
242
+ where: {
243
+ providerUserId: email,
244
+ provider: FFAuthProvider.PASSWORD.id,
245
+ },
246
+ });
247
+ if (existingAccount) {
200
248
  const token = generateId(40);
201
- authAccount.token = token;
202
- authAccount.expiresAt = createDate(new TimeSpan(AUTH_OPTIONS.providers?.password?.resetPasswordExpiresIn ?? 5 * 60, 's'));
203
- await remult.repo(oSafe.Account).save(authAccount);
204
- const url = `${remult.context.url.origin}${oSafe.firstlyData.props.ui.providers.password.paths.reset_password}?token=${token}`;
249
+ existingAccount.token = token;
250
+ existingAccount.expiresAt = createDate(new TimeSpan(AUTH_OPTIONS.providers?.password?.resetPasswordExpiresIn ?? 5 * 60, 's'));
251
+ await remult.repo(oSafe.Account).save(existingAccount);
252
+ const url = `${remult.context.url.origin}${oSafe.firstlyData.props.ui?.paths.reset_password}?token=${token}`;
205
253
  if (AUTH_OPTIONS.providers?.password?.resetPasswordSend) {
206
254
  await AUTH_OPTIONS.providers?.password.resetPasswordSend({ email, url });
207
- logAuth.success(`Done with custom ${green('resetPasswordSend')} (${yellow(url)})`);
255
+ logAuth.success(`${green('[custom]')}${magenta('[resetPasswordSend]')} (${yellow(url)})`);
208
256
  return 'Mail sent !';
209
257
  }
210
258
  else {
211
- await sendMail('forgotPassword', {
259
+ await sendMail('resetPasswordSend', {
212
260
  to: email,
213
261
  subject: 'Reset your password',
214
- text: `You can reset your password here: ${url}`,
215
- html: `You can reset your password <a href="${url}">here</a>`,
262
+ templateProps: {
263
+ title: 'Reset your password 👋',
264
+ previewText: 'This is the mail you were waiting for',
265
+ sections: [
266
+ {
267
+ text: 'Did you forgot something ?',
268
+ highlighted: true,
269
+ },
270
+ {
271
+ text: 'No worries, you can reset your password',
272
+ cta: {
273
+ text: 'HERE',
274
+ link: url,
275
+ },
276
+ },
277
+ ],
278
+ },
216
279
  });
217
- logAuth.success(`Done with ${green('sendMail')} (${url})`);
280
+ logAuth.success(`${magenta('[resetPasswordSend]')} (${yellow(url)})`);
218
281
  return 'Demo Mail sent !';
219
282
  }
220
283
  }
@@ -267,11 +330,11 @@ export class AuthControllerServer {
267
330
  const issuer = AUTH_OPTIONS.providers.otp.issuer ?? 'firstly';
268
331
  const uri = createTOTPKeyURI(issuer, email, secret);
269
332
  const oSafe = getSafeOptions();
270
- let user = await remult.repo(oSafe.User).findFirst({ name: email });
333
+ let user = await remult.repo(oSafe.User).findFirst({ identifier: email });
271
334
  if (!user) {
272
335
  user = remult.repo(oSafe.User).create();
273
336
  }
274
- user.name = email;
337
+ user.identifier = email;
275
338
  user = await remult.repo(oSafe.User).save(user);
276
339
  let account = await remult
277
340
  .repo(oSafe.Account)
@@ -306,7 +369,7 @@ export class AuthControllerServer {
306
369
  }
307
370
  const account = accounts[0];
308
371
  const user = await remult.repo(oSafe.User).findId(account.userId);
309
- if (user?.name !== email) {
372
+ if (user?.identifier !== email) {
310
373
  throw new Error('Invalid otp.');
311
374
  }
312
375
  const { decodeHex } = await import('oslo/encoding');
@@ -7,7 +7,7 @@ export declare class FFAuthUser {
7
7
  id: string;
8
8
  createdAt: Date;
9
9
  updatedAt?: Date;
10
- name: string;
10
+ identifier: string;
11
11
  roles: string[];
12
12
  accounts: FFAuthAccount[];
13
13
  sessions: FFAuthUserSession[];
@@ -14,7 +14,7 @@ let FFAuthUser = class FFAuthUser {
14
14
  id;
15
15
  createdAt;
16
16
  updatedAt;
17
- name;
17
+ identifier;
18
18
  roles = [];
19
19
  accounts;
20
20
  sessions;
@@ -33,12 +33,12 @@ __decorate([
33
33
  validate: [
34
34
  Validators.unique(),
35
35
  (e) => {
36
- if (e.name.length < 2)
36
+ if (e.identifier.length < 2)
37
37
  throw 'Must be at least 2 characters long';
38
38
  },
39
39
  ],
40
40
  })
41
- ], FFAuthUser.prototype, "name", void 0);
41
+ ], FFAuthUser.prototype, "identifier", void 0);
42
42
  __decorate([
43
43
  Fields.object({
44
44
  valueConverter: {
@@ -17,13 +17,13 @@ export const mergeRoles = (existing, newOnes) => {
17
17
  return { roles: Array.from(result), changed };
18
18
  };
19
19
  export const initRoleFromEnv = async (log, userEntity, envValue, role) => {
20
- const names = envValue === undefined ? [] : (envValue ?? '').split(',').map((c) => c.trim());
21
- for (let i = 0; i < names.length; i++) {
22
- const name = names[i].trim();
23
- if (name !== '') {
24
- let user = await repo(userEntity).findFirst({ name });
20
+ const identifiers = envValue === undefined ? [] : (envValue ?? '').split(',').map((c) => c.trim());
21
+ for (let i = 0; i < identifiers.length; i++) {
22
+ const identifier = identifiers[i].trim();
23
+ if (identifier !== '') {
24
+ let user = await repo(userEntity).findFirst({ identifier });
25
25
  if (!user) {
26
- user = repo(userEntity).create({ name, roles: [role] });
26
+ user = repo(userEntity).create({ identifier, roles: [role] });
27
27
  await repo(userEntity).save(user);
28
28
  }
29
29
  else {
@@ -34,8 +34,8 @@ export const initRoleFromEnv = async (log, userEntity, envValue, role) => {
34
34
  }
35
35
  }
36
36
  }
37
- if (names.length > 0) {
38
- log.info(`${cyan(role)}: ${names.map((c) => green(c.trim())).join(', ')} added via ${yellow(`.env`)}.`);
37
+ if (identifiers.length > 0) {
38
+ log.info(`${cyan(role)}: ${identifiers.map((c) => green(c.trim())).join(', ')} added via ${yellow(`.env`)}.`);
39
39
  }
40
40
  else {
41
41
  log.info(`${cyan(role)}: No users added via ${yellow(`.env`)}.`);
@@ -96,7 +96,7 @@ __decorate([
96
96
  BackendMethod({ allowed: true })
97
97
  ], Auth, "signInDemo", null);
98
98
  __decorate([
99
- BackendMethod({ allowed: false })
99
+ BackendMethod({ allowed: true })
100
100
  ], Auth, "invite", null);
101
101
  __decorate([
102
102
  BackendMethod({ allowed: true })
@@ -3,9 +3,9 @@ import { Lucia, type SessionCookieOptions } from 'lucia';
3
3
  import type { ClassType, UserInfo } from 'remult';
4
4
  import { Log } from '@kitql/helpers';
5
5
  import type { Module } from '../api';
6
- import type { ResolvedType } from '../utils/types';
6
+ import type { RecursivePartial, ResolvedType } from '../utils/types';
7
7
  import { FFAuthAccount, FFAuthProvider, FFAuthUser, FFAuthUserSession } from './Entities';
8
- import type { firstlyData } from './types';
8
+ import type { firstlyData, firstlyDataAuth } from './types';
9
9
  export type { firstlyData };
10
10
  export { FFAuthUser, FFAuthAccount, FFAuthProvider, FFAuthUserSession };
11
11
  export type AuthorizationURLOptions = Record<string, {
@@ -35,11 +35,8 @@ type AuthOptions<TUserEntity extends FFAuthUser = FFAuthUser, TSessionEntity ext
35
35
  Session?: ClassType<TSessionEntity>;
36
36
  Account?: ClassType<TAccountEntity>;
37
37
  };
38
- ui?: {
39
- paths?: {
40
- base?: string;
41
- };
42
- } | false;
38
+ debug?: boolean;
39
+ ui?: false | RecursivePartial<firstlyDataAuth['ui']>;
43
40
  /** in secondes @default 15 days */
44
41
  sessionExpiresIn?: number;
45
42
  sessionCookie?: SessionCookieOptions;
package/esm/auth/index.js CHANGED
@@ -15,43 +15,47 @@ import { initRoleFromEnv } from './RoleHelpers';
15
15
  export { FFAuthUser, FFAuthAccount, FFAuthProvider, FFAuthUserSession };
16
16
  export const logAuth = new Log('firstly | auth');
17
17
  export { FF_Auth_Role } from './Entities';
18
- export let AUTH_OPTIONS = {};
18
+ export let AUTH_OPTIONS = { ui: {} };
19
+ const buildUrlOrDefault = (base, userSetting, fallback) => {
20
+ if (userSetting) {
21
+ return `${base}/${userSetting}`;
22
+ }
23
+ return `${base}/${fallback}`;
24
+ };
19
25
  export const getSafeOptions = () => {
20
26
  const signUp = AUTH_OPTIONS.signUp ?? true;
21
27
  const base = AUTH_OPTIONS.ui === false ? 'NO_BASE_PATH' : AUTH_OPTIONS.ui?.paths?.base ?? '/ff/auth';
22
- const oAuths = AUTH_OPTIONS.providers?.oAuths?.map((o) => {
23
- return o.name;
24
- }) ?? [];
28
+ // const oAuths =
29
+ // AUTH_OPTIONS.providers?.oAuths?.map((o) => {
30
+ // return o.name
31
+ // }) ?? []
25
32
  const firstlyData = {
26
33
  module: 'auth',
34
+ debug: AUTH_OPTIONS.debug,
27
35
  props: {
28
- ui: {
29
- paths: {
30
- base,
31
- },
32
- providers: {
33
- password: {
34
- dico: {
35
- email: 'Email',
36
- email_placeholder: 'Your email address',
37
- password: 'Password',
38
- btn_sign_up: 'Sign up',
39
- btn_sign_in: 'Sign in',
40
- forgot_password: 'Forgot your password?',
41
- send_password_reset_instructions: 'Send password reset instructions',
42
- back_to_sign_in: 'Back to sign in',
43
- },
44
- paths: {
45
- sign_up: signUp ? `${base}/sign-up` : false,
46
- sign_in: `${base}/sign-in`,
47
- forgot_password: `${base}/forgot-password`,
48
- reset_password: `${base}/reset-password`,
49
- verify_email: `${base}/verify-email`,
50
- },
36
+ ui: AUTH_OPTIONS.ui === false
37
+ ? undefined
38
+ : {
39
+ paths: {
40
+ base,
41
+ sign_up: buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.sign_up, 'sign-up'),
42
+ sign_in: buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.sign_in, 'sign-in'),
43
+ forgot_password: buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.forgot_password, 'forgot-password'),
44
+ reset_password: buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.reset_password, 'reset-password'),
45
+ verify_email: buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.verify_email, 'verify-email'),
46
+ },
47
+ strings: {
48
+ email: AUTH_OPTIONS.ui?.strings?.email ?? 'Email',
49
+ email_placeholder: AUTH_OPTIONS.ui?.strings?.email_placeholder ?? 'Your email address',
50
+ password: AUTH_OPTIONS.ui?.strings?.password ?? 'Password',
51
+ btn_sign_up: AUTH_OPTIONS.ui?.strings?.btn_sign_up ?? 'Sign up',
52
+ btn_sign_in: AUTH_OPTIONS.ui?.strings?.btn_sign_in ?? 'Sign in',
53
+ forgot_password: AUTH_OPTIONS.ui?.strings?.forgot_password ?? 'Forgot your password?',
54
+ send_password_reset_instructions: AUTH_OPTIONS.ui?.strings?.send_password_reset_instructions ??
55
+ 'Send password reset instructions',
56
+ back_to_sign_in: AUTH_OPTIONS.ui?.strings?.back_to_sign_in ?? 'Back to sign in',
51
57
  },
52
- oAuths,
53
58
  },
54
- },
55
59
  },
56
60
  };
57
61
  let redirectUrl = AUTH_OPTIONS.defaultRedirect ?? '/';
@@ -110,11 +114,11 @@ export const auth = (o) => {
110
114
  }
111
115
  },
112
116
  earlyReturn: async ({ event, resolve }) => {
113
- if (AUTH_OPTIONS.ui === false) {
114
- return { early: false };
115
- }
117
+ // if (AUTH_OPTIONS.ui === false) {
118
+ // return { early: false }
119
+ // }
116
120
  const oSafe = getSafeOptions();
117
- if (event.url.pathname === oSafe.firstlyData.props.ui.providers.password.paths.verify_email) {
121
+ if (event.url.pathname === oSafe.firstlyData.props.ui?.paths?.verify_email) {
118
122
  const token = event.url.searchParams.get('token') ?? '';
119
123
  if (!oSafe.password_enabled) {
120
124
  throw Error('Password is not enabled!');
@@ -144,7 +148,8 @@ export const auth = (o) => {
144
148
  if (installedFirstlyPath) {
145
149
  staticPath = `${installedFirstlyPath}/esm/auth/static/`;
146
150
  }
147
- if (event.url.pathname.startsWith(oSafe.firstlyData.props.ui.paths.base)) {
151
+ if (oSafe.firstlyData.props.ui?.paths?.base &&
152
+ event.url.pathname.startsWith(oSafe.firstlyData.props.ui.paths.base)) {
148
153
  const content = read(`${staticPath}index.html`);
149
154
  return {
150
155
  early: true,
@@ -218,7 +223,7 @@ export const auth = (o) => {
218
223
  for (let i = 0; i < info.nameOptions.length; i++) {
219
224
  const existingUser = await remult
220
225
  .repo(oSafe.User)
221
- .findOne({ where: { name: info.nameOptions[i] } });
226
+ .findOne({ where: { identifier: info.nameOptions[i] } });
222
227
  if (existingUser) {
223
228
  // Don't do anything
224
229
  }
@@ -231,7 +236,7 @@ export const auth = (o) => {
231
236
  nameToUse = `${info.nameOptions[0]}-${info.providerUserId}`;
232
237
  }
233
238
  const user = remult.repo(oSafe.User).create();
234
- user.name = nameToUse;
239
+ user.identifier = nameToUse;
235
240
  account = remult.repo(oSafe.Account).create();
236
241
  account.provider = keyState;
237
242
  account.providerUserId = info.providerUserId;
@@ -0,0 +1 @@
1
+ form.s-KT008SdmQprk,form.s-N0DaQgJ_T5_C,form.s-85Tmcm64bnMI{display:flex;flex-direction:column}.message.s-85Tmcm64bnMI:empty{display:none}.message.s-85Tmcm64bnMI{background:var(--pico-muted-border-color);padding:var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);border-radius:var(--pico-border-radius);margin-bottom:calc(var(--pico-typography-spacing-vertical) * 2)}.message.error.s-85Tmcm64bnMI{background:var(--pico-del-color);color:#4c1513}form.s-FRwn6sVlvC6z{display:flex;flex-direction:column}.message.s-FRwn6sVlvC6z:empty{display:none}.message.s-FRwn6sVlvC6z{background:var(--pico-muted-border-color);padding:var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);border-radius:var(--pico-border-radius);margin-bottom:calc(var(--pico-typography-spacing-vertical) * 2)}.message.error.s-FRwn6sVlvC6z{background:var(--pico-del-color);color:#4c1513}.wrapper.s-NO-a_LAEXXH5{min-height:100vh;display:flex;justify-content:center;align-items:center;margin:0 auto}.form.s-NO-a_LAEXXH5{padding:1rem;max-width:360px;width:100%}.form-footer.s-NO-a_LAEXXH5{margin-top:1rem;display:flex;flex-direction:column;justify-content:center;align-items:center}.fallback.s-NO-a_LAEXXH5{display:flex;justify-content:center;align-items:center}
@@ -0,0 +1,4 @@
1
+ export { v as default };
2
+ declare class v extends l {
3
+ }
4
+ import { S as l } from "./index-qfq98Nyd.js";