firstly 0.0.11 → 0.0.13

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 (139) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/esm/BaseEnum.d.ts +2 -0
  3. package/esm/BaseEnum.js +2 -0
  4. package/esm/FF_Fields.js +0 -1
  5. package/esm/ROUTES.d.ts +2 -2
  6. package/esm/ROUTES.js +10 -5
  7. package/esm/SqlDatabase/FF_LogToConsole.d.ts +1 -0
  8. package/esm/SqlDatabase/FF_LogToConsole.js +22 -16
  9. package/esm/api/index.d.ts +20 -21
  10. package/esm/api/index.js +74 -62
  11. package/esm/auth/{client/Auth.d.ts → AuthController.d.ts} +18 -25
  12. package/esm/auth/{client/Auth.js → AuthController.js} +48 -44
  13. package/esm/auth/{client/Entities.d.ts → Entities.d.ts} +4 -3
  14. package/esm/auth/{client/Entities.js → Entities.js} +7 -7
  15. package/esm/auth/README.md +0 -10
  16. package/esm/auth/index.d.ts +5 -149
  17. package/esm/auth/index.js +5 -316
  18. package/esm/auth/{AuthController.server.d.ts → server/AuthController.server.d.ts} +10 -10
  19. package/esm/auth/{AuthController.server.js → server/AuthController.server.js} +133 -171
  20. package/esm/auth/server/handleAuth.d.ts +2 -0
  21. package/esm/auth/server/handleAuth.js +140 -0
  22. package/esm/auth/server/handleGuard.d.ts +16 -0
  23. package/esm/auth/server/handleGuard.js +67 -0
  24. package/esm/auth/server/helperDb.d.ts +10 -0
  25. package/esm/auth/server/helperDb.js +56 -0
  26. package/esm/auth/server/helperFirstly.d.ts +1 -0
  27. package/esm/auth/server/helperFirstly.js +8 -0
  28. package/esm/auth/server/helperOslo.d.ts +7 -0
  29. package/esm/auth/server/helperOslo.js +24 -0
  30. package/esm/auth/server/helperRemultServer.d.ts +5 -0
  31. package/esm/auth/server/helperRemultServer.js +44 -0
  32. package/esm/auth/{RoleHelpers.d.ts → server/helperRole.d.ts} +1 -1
  33. package/esm/auth/{RoleHelpers.js → server/helperRole.js} +1 -1
  34. package/esm/auth/server/index.d.ts +7 -0
  35. package/esm/auth/server/index.js +7 -0
  36. package/esm/auth/server/module.d.ts +257 -0
  37. package/esm/auth/server/module.js +197 -0
  38. package/esm/auth/{providers → server/providers}/github.d.ts +6 -4
  39. package/esm/auth/{providers → server/providers}/github.js +29 -20
  40. package/esm/auth/{providers/index.d.ts → server/providers/helperProvider.d.ts} +0 -2
  41. package/esm/auth/{providers/index.js → server/providers/helperProvider.js} +5 -6
  42. package/esm/auth/static/assets/Page-BUfjaN-D.d.ts +5 -0
  43. package/esm/auth/static/assets/Page-BUfjaN-D.js +19 -0
  44. package/esm/auth/static/assets/Page-CJ58H1vl.css +1 -0
  45. package/esm/auth/static/assets/Page-CaDAqmBS.d.ts +5 -0
  46. package/esm/auth/static/assets/Page-CaDAqmBS.js +1 -0
  47. package/esm/auth/static/assets/Page-DhdZddzJ.d.ts +5 -0
  48. package/esm/auth/static/assets/Page-DhdZddzJ.js +1 -0
  49. package/esm/auth/static/assets/index-BDy4A_14.css +4 -0
  50. package/esm/auth/static/assets/index-D-Ztdt2o.d.ts +54 -0
  51. package/esm/auth/static/assets/index-D-Ztdt2o.js +2 -0
  52. package/esm/auth/static/index.html +11 -11
  53. package/esm/auth/types.d.ts +5 -0
  54. package/esm/bin/cmd.js +122 -54
  55. package/esm/cellsBuildor.js +7 -7
  56. package/esm/changeLog/index.d.ts +0 -36
  57. package/esm/changeLog/index.js +3 -43
  58. package/esm/changeLog/server/index.d.ts +36 -0
  59. package/esm/changeLog/server/index.js +42 -0
  60. package/esm/common.d.ts +5 -0
  61. package/esm/common.js +8 -0
  62. package/esm/cron/{index.d.ts → server/index.d.ts} +1 -1
  63. package/esm/cron/server/index.js +103 -0
  64. package/esm/feedback/FeedbackController.js +4 -5
  65. package/esm/feedback/index.d.ts +0 -16
  66. package/esm/feedback/index.js +0 -11
  67. package/esm/feedback/server/index.d.ts +17 -0
  68. package/esm/feedback/server/index.js +13 -0
  69. package/esm/feedback/ui/DialogIssue.svelte +52 -56
  70. package/esm/feedback/ui/DialogIssues.svelte +71 -71
  71. package/esm/feedback/ui/DialogMilestones.svelte +22 -22
  72. package/esm/helper.js +3 -3
  73. package/esm/index.d.ts +3 -20
  74. package/esm/index.js +3 -10
  75. package/esm/mail/index.d.ts +2 -30
  76. package/esm/mail/index.js +2 -79
  77. package/esm/mail/server/index.d.ts +31 -0
  78. package/esm/mail/server/index.js +88 -0
  79. package/esm/mail/templates/DefaultMail.svelte +17 -17
  80. package/esm/storeItem.js +8 -2
  81. package/esm/storeList.d.ts +1 -1
  82. package/esm/storeList.js +1 -1
  83. package/esm/sveltekit/server/index.d.ts +14 -0
  84. package/esm/sveltekit/server/index.js +24 -0
  85. package/esm/ui/Button.svelte +33 -33
  86. package/esm/ui/Button.svelte.d.ts +2 -2
  87. package/esm/ui/Clipboardable.svelte +11 -8
  88. package/esm/ui/Clipboardable.svelte.d.ts +4 -4
  89. package/esm/ui/Field.svelte +142 -149
  90. package/esm/ui/Field.svelte.d.ts +2 -2
  91. package/esm/ui/FieldGroup.svelte +38 -38
  92. package/esm/ui/Grid.svelte +212 -222
  93. package/esm/ui/GridLoading.svelte +18 -22
  94. package/esm/ui/GridPaginate.svelte +38 -38
  95. package/esm/ui/Icon.svelte +50 -49
  96. package/esm/ui/Icon.svelte.d.ts +18 -18
  97. package/esm/ui/Loading.svelte +5 -2
  98. package/esm/ui/Tooltip.svelte +16 -16
  99. package/esm/ui/dialog/DialogForm.svelte +23 -23
  100. package/esm/ui/dialog/DialogManagement.svelte +74 -74
  101. package/esm/ui/dialog/DialogPrimitive.svelte +50 -51
  102. package/esm/ui/dialog/FormEditAction.svelte +34 -34
  103. package/esm/ui/dialog/dialog.d.ts +2 -2
  104. package/esm/ui/dialog/dialog.js +1 -1
  105. package/esm/ui/internals/FieldContainer.svelte +11 -12
  106. package/esm/ui/internals/FieldContainer.svelte.d.ts +3 -3
  107. package/esm/ui/internals/Input.svelte +25 -25
  108. package/esm/ui/internals/Input.svelte.d.ts +1 -1
  109. package/esm/ui/internals/Textarea.svelte +21 -21
  110. package/esm/ui/internals/Textarea.svelte.d.ts +2 -2
  111. package/esm/ui/internals/select/MultiSelectMelt.svelte +69 -73
  112. package/esm/ui/internals/select/SelectMelt.svelte +86 -86
  113. package/esm/ui/internals/select/SelectRadio.svelte +22 -22
  114. package/esm/ui/link/Link.svelte +14 -14
  115. package/esm/ui/link/Link.svelte.d.ts +3 -4
  116. package/esm/ui/link/LinkPlus.svelte +33 -35
  117. package/esm/vite/index.js +24 -25
  118. package/package.json +50 -42
  119. package/esm/auth/Adapter.d.ts +0 -10
  120. package/esm/auth/Adapter.js +0 -50
  121. package/esm/auth/client/index.d.ts +0 -7
  122. package/esm/auth/client/index.js +0 -7
  123. package/esm/auth/helper.d.ts +0 -6
  124. package/esm/auth/helper.js +0 -14
  125. package/esm/auth/providers/strava.d.ts +0 -30
  126. package/esm/auth/providers/strava.js +0 -60
  127. package/esm/auth/static/assets/Page-BEFYPjis.d.ts +0 -4
  128. package/esm/auth/static/assets/Page-BEFYPjis.js +0 -1
  129. package/esm/auth/static/assets/Page-BGTO8LC5.css +0 -1
  130. package/esm/auth/static/assets/Page-Cfysx_UV.d.ts +0 -6
  131. package/esm/auth/static/assets/Page-Cfysx_UV.js +0 -18
  132. package/esm/auth/static/assets/Page-DtgkOCJs.d.ts +0 -4
  133. package/esm/auth/static/assets/Page-DtgkOCJs.js +0 -1
  134. package/esm/auth/static/assets/index-CR_3yNaJ.css +0 -4
  135. package/esm/auth/static/assets/index-QypqCYwC.d.ts +0 -63
  136. package/esm/auth/static/assets/index-QypqCYwC.js +0 -2
  137. package/esm/cron/index.js +0 -102
  138. package/esm/handle/index.d.ts +0 -7
  139. package/esm/handle/index.js +0 -40
@@ -0,0 +1,257 @@
1
+ import type { OAuth2Tokens } from 'arctic';
2
+ import type { ClassType, UserInfo } from 'remult';
3
+ import { Module } from '../../api';
4
+ import type { RecursivePartial } from '../../utils/types';
5
+ import { FFAuthAccount, FFAuthUser, FFAuthUserSession } from '../Entities';
6
+ import type { firstlyData, firstlyDataAuth } from '../types';
7
+ import { initRoleFromEnv } from './helperRole';
8
+ export type { firstlyData };
9
+ export type ProviderConfigured = Record<string, ProviderAuthorizationURLOptions>;
10
+ export type ProviderAuthorizationURLOptions = string[];
11
+ export type OAuth2UserInfo = {
12
+ raw?: any;
13
+ providerUserId: string;
14
+ /** Will take the first option available */
15
+ nameOptions: string[];
16
+ };
17
+ export type FFOAuth2Provider<T = any, LitName extends string = string> = {
18
+ name: LitName;
19
+ getArcticProvider: () => T;
20
+ authorizationURLOptions: () => ProviderAuthorizationURLOptions;
21
+ getUserInfo(tokens: OAuth2Tokens): Promise<OAuth2UserInfo>;
22
+ };
23
+ type AuthOptions<TUserEntity extends FFAuthUser = FFAuthUser, TSessionEntity extends FFAuthUserSession = FFAuthUserSession, TAccountEntity extends FFAuthAccount = FFAuthAccount> = {
24
+ customEntities?: {
25
+ User?: ClassType<TUserEntity>;
26
+ Session?: ClassType<TSessionEntity>;
27
+ Account?: ClassType<TAccountEntity>;
28
+ };
29
+ debug?: boolean;
30
+ ui?: false | RecursivePartial<firstlyDataAuth['ui']>;
31
+ strings?: {
32
+ resetPasswordSend?: string;
33
+ anErrorOccurred?: string;
34
+ cannotSignUp?: string;
35
+ };
36
+ /** Usefull to overwrite where the static files are */
37
+ uiStaticPath?: string;
38
+ session?: {
39
+ /** in milliseconds @default 30 days (1000 * 60 * 60 * 24 * 30) */
40
+ expiresIn?: number;
41
+ COOKIE_NAME?: string;
42
+ };
43
+ defaultRedirect?: string;
44
+ /**
45
+ * Can a user sign up by itself? Or we can join only by invitation ?
46
+ * If false, no one can sign up alone.
47
+ * @default true
48
+ **/
49
+ signUp?: boolean;
50
+ /**
51
+ * To be able to sign in user needs to be verified or not?
52
+ * ```
53
+ * `Auto` => noting will be checked
54
+ * `Email` => users needs to click a link in an email
55
+ * `Manual` => an admin needs to verify the user and set verifiedAt in the database
56
+ * ```
57
+ * @default auto
58
+ **/
59
+ verifiedMethod?: 'auto' | 'email' | 'manual';
60
+ invitationSend?: (args: {
61
+ email: string;
62
+ url: string;
63
+ }) => Promise<void>;
64
+ transformDbUserToClientUser?: (session: TSessionEntity, user: TUserEntity) => UserInfo;
65
+ providers?: {
66
+ demo?: {
67
+ name: string;
68
+ roles?: string[];
69
+ }[];
70
+ password?: {
71
+ mail?: {
72
+ reset?: {
73
+ send?: (args: {
74
+ email: string;
75
+ url: string;
76
+ }) => Promise<void>;
77
+ /** in secondes @default 5 minutes */
78
+ expiresIn?: number;
79
+ };
80
+ verify?: {
81
+ send?: (args: {
82
+ email: string;
83
+ url: string;
84
+ }) => Promise<void>;
85
+ /** in secondes @default 5 minutes */
86
+ expiresIn?: number;
87
+ };
88
+ };
89
+ algo?: {
90
+ /**
91
+ * Validate the password or throw an error.
92
+ *
93
+ * Here is an example (and it's the default implementation):
94
+ * ```
95
+ * function validatePassword(password: string) {
96
+ * if (typeof password !== 'string' || password.length < 6 || password.length > 255) {
97
+ * throw new EntityError({ message: 'Invalid password' })
98
+ * }
99
+ * }
100
+ * ```
101
+ */
102
+ validateInput?: ({ identifier, password }: {
103
+ identifier: string;
104
+ password: string;
105
+ }) => void;
106
+ /**
107
+ * If you want to NOT use the default bcrypt, you can pass your own thing!
108
+ */
109
+ hash?: (password: string) => Promise<string>;
110
+ /**
111
+ * If you want to NOT use the default bcrypt, you can pass your own thing!
112
+ */
113
+ verify?: (password: string, hash: string) => Promise<boolean>;
114
+ bcrypt?: {
115
+ /**
116
+ * The number of rounds to use for the bcrypt hash.
117
+ * @default 10
118
+ */
119
+ saltRounds?: number;
120
+ };
121
+ };
122
+ };
123
+ otp?: {
124
+ issuer?: string;
125
+ /** in secondes @default 30 seconds */
126
+ expiresIn?: number;
127
+ /** Number of digits @default 6 */
128
+ digits?: number;
129
+ send?: (data: {
130
+ name: string;
131
+ otp: string;
132
+ uri: string;
133
+ }) => Promise<void>;
134
+ };
135
+ oAuths?: FFOAuth2Provider[];
136
+ };
137
+ };
138
+ export declare let AUTH_OPTIONS: AuthOptions;
139
+ export declare const getSafeOptions: <TUserEntity extends FFAuthUser = FFAuthUser, TSessionEntity extends FFAuthUserSession = FFAuthUserSession, TAccountEntity extends FFAuthAccount = FFAuthAccount>() => {
140
+ User: ClassType<TUserEntity>;
141
+ Session: ClassType<TSessionEntity>;
142
+ Account: ClassType<TAccountEntity>;
143
+ signUp: boolean;
144
+ password: {
145
+ enabled: boolean;
146
+ validateInput: ({ identifier, password }: {
147
+ identifier: string;
148
+ password: string;
149
+ }) => void;
150
+ hash: ((password: string) => Promise<string>) | ((password: string) => string);
151
+ verify: ((password: string, hash: string) => Promise<boolean>) | ((password: string, hash: string) => boolean);
152
+ };
153
+ otp: {
154
+ enabled: boolean;
155
+ };
156
+ verifiedMethod: "email" | "auto" | "manual";
157
+ redirectUrl: string;
158
+ firstlyData: firstlyData;
159
+ transformDbUserToClientUser: (session: TSessionEntity, user: TUserEntity) => UserInfo;
160
+ uiStaticPath: string;
161
+ session: {
162
+ expiresInMs: number;
163
+ cookieName: string;
164
+ };
165
+ providers: {
166
+ demo?: {
167
+ name: string;
168
+ roles?: string[];
169
+ }[];
170
+ password?: {
171
+ mail?: {
172
+ reset?: {
173
+ send?: (args: {
174
+ email: string;
175
+ url: string;
176
+ }) => Promise<void>;
177
+ /** in secondes @default 5 minutes */
178
+ expiresIn?: number;
179
+ };
180
+ verify?: {
181
+ send?: (args: {
182
+ email: string;
183
+ url: string;
184
+ }) => Promise<void>;
185
+ /** in secondes @default 5 minutes */
186
+ expiresIn?: number;
187
+ };
188
+ };
189
+ algo?: {
190
+ /**
191
+ * Validate the password or throw an error.
192
+ *
193
+ * Here is an example (and it's the default implementation):
194
+ * ```
195
+ * function validatePassword(password: string) {
196
+ * if (typeof password !== 'string' || password.length < 6 || password.length > 255) {
197
+ * throw new EntityError({ message: 'Invalid password' })
198
+ * }
199
+ * }
200
+ * ```
201
+ */
202
+ validateInput?: ({ identifier, password }: {
203
+ identifier: string;
204
+ password: string;
205
+ }) => void;
206
+ /**
207
+ * If you want to NOT use the default bcrypt, you can pass your own thing!
208
+ */
209
+ hash?: (password: string) => Promise<string>;
210
+ /**
211
+ * If you want to NOT use the default bcrypt, you can pass your own thing!
212
+ */
213
+ verify?: (password: string, hash: string) => Promise<boolean>;
214
+ bcrypt?: {
215
+ /**
216
+ * The number of rounds to use for the bcrypt hash.
217
+ * @default 10
218
+ */
219
+ saltRounds?: number;
220
+ };
221
+ };
222
+ };
223
+ otp?: {
224
+ issuer?: string;
225
+ /** in secondes @default 30 seconds */
226
+ expiresIn?: number;
227
+ /** Number of digits @default 6 */
228
+ digits?: number;
229
+ send?: (data: {
230
+ name: string;
231
+ otp: string;
232
+ uri: string;
233
+ }) => Promise<void>;
234
+ };
235
+ oAuths?: FFOAuth2Provider[];
236
+ } | undefined;
237
+ strings: {
238
+ resetPasswordSend: string;
239
+ anErrorOccurred: string;
240
+ cannotSignUp: string;
241
+ };
242
+ };
243
+ export declare const authModuleRaw: Module;
244
+ /**
245
+ * To enable authentication in your app in a few lines of code.
246
+ * _Info: index: -777_
247
+ */
248
+ export declare const auth: <TUserEntity extends FFAuthUser = FFAuthUser, TSessionEntity extends FFAuthUserSession = FFAuthUserSession, TAccountEntity extends FFAuthAccount = FFAuthAccount>(o: AuthOptions<TUserEntity, TSessionEntity, TAccountEntity>) => Module;
249
+ export { initRoleFromEnv };
250
+ declare module 'remult' {
251
+ interface UserInfo {
252
+ session: {
253
+ id: string;
254
+ expiresAt: Date;
255
+ };
256
+ }
257
+ }
@@ -0,0 +1,197 @@
1
+ import bcrypt from 'bcryptjs';
2
+ import { EntityError, remult } from 'remult';
3
+ import { red } from '@kitql/helpers';
4
+ import { getRelativePackagePath } from '@kitql/internals';
5
+ import { building } from '$app/environment';
6
+ import { AuthController } from '..';
7
+ import { FF_Role } from '../..';
8
+ import { Module } from '../../api';
9
+ import { FF_Role_Auth, FFAuthAccount, FFAuthUser, FFAuthUserSession } from '../Entities';
10
+ import { AuthControllerServer } from './AuthController.server';
11
+ import { validateSessionToken } from './helperDb';
12
+ import { setSessionTokenCookie } from './helperRemultServer';
13
+ import { initRoleFromEnv } from './helperRole';
14
+ export let AUTH_OPTIONS = { ui: {} };
15
+ const buildUrlOrDefault = (base, userSetting, fallback) => {
16
+ if (userSetting === false) {
17
+ return false;
18
+ }
19
+ if (userSetting === undefined) {
20
+ return `${base}/${fallback}`;
21
+ }
22
+ return `${base}/${userSetting}`;
23
+ };
24
+ export const getSafeOptions = () => {
25
+ const signUp = AUTH_OPTIONS.signUp ?? true;
26
+ const base = AUTH_OPTIONS.ui === false ? 'NO_BASE_PATH' : (AUTH_OPTIONS.ui?.paths?.base ?? '/ff/auth');
27
+ const ui = AUTH_OPTIONS.ui === false
28
+ ? undefined
29
+ : {
30
+ paths: {
31
+ base,
32
+ sign_up: signUp ? buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.sign_up, 'sign-up') : false,
33
+ sign_in: buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.sign_in, 'sign-in'),
34
+ forgot_password: buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.forgot_password, 'forgot-password'),
35
+ reset_password: buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.reset_password, 'reset-password'),
36
+ verify_email: buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.verify_email, 'verify-email'),
37
+ },
38
+ strings: {
39
+ app_name: AUTH_OPTIONS.ui?.strings?.app_name ?? '',
40
+ email: AUTH_OPTIONS.ui?.strings?.email ?? 'Email',
41
+ email_placeholder: AUTH_OPTIONS.ui?.strings?.email_placeholder ?? 'Your email address',
42
+ password: AUTH_OPTIONS.ui?.strings?.password ?? 'Password',
43
+ password_placeholder: AUTH_OPTIONS.ui?.strings?.password_placeholder ?? 'Your password',
44
+ confirm: AUTH_OPTIONS.ui?.strings?.confirm ?? 'Confirm',
45
+ reset: AUTH_OPTIONS.ui?.strings?.reset ?? 'Reset',
46
+ btn_sign_up: AUTH_OPTIONS.ui?.strings?.btn_sign_up ?? 'Sign up',
47
+ btn_sign_in: AUTH_OPTIONS.ui?.strings?.btn_sign_in ?? 'Sign in',
48
+ forgot_password: AUTH_OPTIONS.ui?.strings?.forgot_password ?? 'Forgot your password?',
49
+ send_password_reset_instructions: AUTH_OPTIONS.ui?.strings?.send_password_reset_instructions ??
50
+ 'Send password reset instructions',
51
+ back_to_sign_in: AUTH_OPTIONS.ui?.strings?.back_to_sign_in ?? 'Back to sign in',
52
+ },
53
+ images: {
54
+ main: AUTH_OPTIONS.ui?.images?.main ?? '',
55
+ },
56
+ };
57
+ if (AUTH_OPTIONS.debug && !building) {
58
+ authModuleRaw.log.info('ui', ui);
59
+ }
60
+ const firstlyData = {
61
+ module: 'auth',
62
+ debug: AUTH_OPTIONS.debug,
63
+ props: {
64
+ ui,
65
+ },
66
+ };
67
+ let uiStaticPath = AUTH_OPTIONS.uiStaticPath ?? '';
68
+ if (!AUTH_OPTIONS.uiStaticPath) {
69
+ const installedFirstlyPath = getRelativePackagePath('firstly');
70
+ if (installedFirstlyPath) {
71
+ uiStaticPath = `${installedFirstlyPath}/esm/auth/static/`;
72
+ }
73
+ }
74
+ let redirectUrl = AUTH_OPTIONS.defaultRedirect ?? '/';
75
+ if (!redirectUrl.startsWith('/')) {
76
+ authModuleRaw.log.error(`Invalid redirect url ${red(redirectUrl)} (it should be a local one starting with /)`);
77
+ redirectUrl = '/';
78
+ }
79
+ let transformDbUserToClientUserToUse;
80
+ if (AUTH_OPTIONS.transformDbUserToClientUser) {
81
+ transformDbUserToClientUserToUse = AUTH_OPTIONS.transformDbUserToClientUser;
82
+ }
83
+ else {
84
+ // @ts-ignore (I'm not sure why cadb-my-doc is failing check here if I don't do this!)
85
+ transformDbUserToClientUserToUse = (session, user) => {
86
+ return {
87
+ id: user.id,
88
+ name: user.identifier,
89
+ roles: user.roles,
90
+ session: {
91
+ id: session.id,
92
+ expiresAt: session.expiresAt,
93
+ },
94
+ };
95
+ };
96
+ }
97
+ function validateInput({ identifier, password }) {
98
+ if (typeof identifier !== 'string' || identifier.length === 0) {
99
+ throw new EntityError({ message: 'Invalid identifier' });
100
+ }
101
+ if (typeof password !== 'string') {
102
+ throw new EntityError({ message: 'Invalid password' });
103
+ }
104
+ if (password.length < 6 || password.length > 255) {
105
+ throw new EntityError({ message: 'Password too short or too long!' });
106
+ }
107
+ }
108
+ function passwordHash(password) {
109
+ return bcrypt.hashSync(password, AUTH_OPTIONS.providers?.password?.algo?.bcrypt?.saltRounds ?? 10);
110
+ }
111
+ function passwordVerify(password, hash) {
112
+ return bcrypt.compareSync(password, hash);
113
+ }
114
+ return {
115
+ User: (AUTH_OPTIONS.customEntities?.User ?? FFAuthUser),
116
+ Session: (AUTH_OPTIONS.customEntities?.Session ?? FFAuthUserSession),
117
+ Account: (AUTH_OPTIONS.customEntities?.Account ?? FFAuthAccount),
118
+ signUp,
119
+ password: {
120
+ enabled: AUTH_OPTIONS.providers?.password ? true : false,
121
+ validateInput: AUTH_OPTIONS.providers?.password?.algo?.validateInput ?? validateInput,
122
+ hash: AUTH_OPTIONS.providers?.password?.algo?.hash ?? passwordHash,
123
+ verify: AUTH_OPTIONS.providers?.password?.algo?.verify ?? passwordVerify,
124
+ },
125
+ otp: { enabled: AUTH_OPTIONS.providers?.otp ? true : false },
126
+ verifiedMethod: AUTH_OPTIONS.verifiedMethod ?? 'auto',
127
+ redirectUrl,
128
+ firstlyData,
129
+ transformDbUserToClientUser: transformDbUserToClientUserToUse,
130
+ uiStaticPath,
131
+ session: {
132
+ expiresInMs: AUTH_OPTIONS.session?.expiresIn ?? 1000 * 60 * 60 * 24 * 30, // 30 days,
133
+ cookieName: AUTH_OPTIONS.session?.COOKIE_NAME ?? 'firstly_auth_session',
134
+ },
135
+ providers: AUTH_OPTIONS.providers,
136
+ strings: {
137
+ resetPasswordSend: AUTH_OPTIONS.strings?.resetPasswordSend ?? 'Mail sent ! You can now close this window.',
138
+ anErrorOccurred: AUTH_OPTIONS.strings?.anErrorOccurred ?? 'An error occurred, contact the administrator.',
139
+ cannotSignUp: AUTH_OPTIONS.strings?.cannotSignUp ??
140
+ "You can't signup by yourself! Contact the administrator.",
141
+ },
142
+ };
143
+ };
144
+ export const authModuleRaw = new Module({
145
+ name: 'auth',
146
+ priority: -777,
147
+ });
148
+ /**
149
+ * To enable authentication in your app in a few lines of code.
150
+ * _Info: index: -777_
151
+ */
152
+ export const auth = (o) => {
153
+ // TODO should work ?
154
+ // @ts-ignore
155
+ AUTH_OPTIONS = o;
156
+ const oSafe = getSafeOptions();
157
+ // Replace the direct assignments with the new _setImplementation method
158
+ AuthController._setAbstraction({
159
+ signOut: AuthControllerServer.signOut,
160
+ signInDemo: AuthControllerServer.signInDemo,
161
+ invite: AuthControllerServer.invite,
162
+ signUpPassword: AuthControllerServer.signUpPassword,
163
+ signInPassword: AuthControllerServer.signInPassword,
164
+ forgotPassword: AuthControllerServer.forgotPassword,
165
+ resetPassword: AuthControllerServer.resetPassword,
166
+ signInOTP: AuthControllerServer.signInOTP,
167
+ verifyOtp: AuthControllerServer.verifyOtp,
168
+ signInOAuthGetUrl: AuthControllerServer.signInOAuthGetUrl,
169
+ });
170
+ authModuleRaw.entities = [oSafe.User, oSafe.Session, oSafe.Account];
171
+ authModuleRaw.controllers = [AuthController];
172
+ authModuleRaw.initRequest = async (event) => {
173
+ // REMULT: storing user in local should probably be done in remult directly
174
+ if (event?.locals?.user) {
175
+ remult.user = event.locals.user;
176
+ }
177
+ else {
178
+ const sessionId = event.cookies.get(oSafe.session.cookieName);
179
+ if (sessionId) {
180
+ const { user, freshSession } = await validateSessionToken(sessionId);
181
+ if (freshSession) {
182
+ setSessionTokenCookie(freshSession.sessionToken, freshSession.expiresAt);
183
+ }
184
+ remult.user = user;
185
+ if (event.locals) {
186
+ event.locals.user = user;
187
+ }
188
+ }
189
+ }
190
+ };
191
+ authModuleRaw.initApi = async () => {
192
+ await initRoleFromEnv(authModuleRaw.log, oSafe.User, 'FF_ROLE_ADMIN', FF_Role.FF_Role_Admin);
193
+ await initRoleFromEnv(authModuleRaw.log, oSafe.User, 'FF_ROLE_AUTH_ADMIN', FF_Role_Auth.FF_Role_Auth_Admin);
194
+ };
195
+ return authModuleRaw;
196
+ };
197
+ export { initRoleFromEnv };
@@ -1,11 +1,12 @@
1
+ import type { OAuth2Tokens } from 'arctic';
1
2
  import { GitHub } from 'arctic';
2
- import { type FFOAuth2Provider } from '../';
3
+ import { type FFOAuth2Provider, type OAuth2UserInfo, type ProviderAuthorizationURLOptions } from '../module';
3
4
  /**
4
5
  * ## GitHub OAuth2 provider
5
6
  *
6
7
  * 1. Get your **id** & **secret** from [GitHub (direct link)](https://github.com/settings/developers).
7
8
  * 2. In GitHub, set your callback url to
8
- * - [ ] dev: `http://localhost:5173/api/auth_callback`
9
+ * - [ ] dev: `http://_YOUR_LOCAL_URL:PORT_/api/auth_callback`
9
10
  * - [ ] prod: `https://MY_SUPER_SITE/api/auth_callback`
10
11
  * 3. In your project add a `.env` file with the following:
11
12
  * ```bash
@@ -25,6 +26,7 @@ export declare function github(options?: {
25
26
  GITHUB_CLIENT_ID?: string;
26
27
  GITHUB_CLIENT_SECRET?: string;
27
28
  GITHUB_REDIRECT_URI?: string;
28
- authorizationURLOptions?: ReturnType<FFOAuth2Provider<'github', GitHub>['authorizationURLOptions']>;
29
+ authorizationURLOptions?: ProviderAuthorizationURLOptions;
30
+ getUserInfo?: (tokens: OAuth2Tokens) => Promise<OAuth2UserInfo>;
29
31
  log?: boolean;
30
- }): FFOAuth2Provider<'github', GitHub>;
32
+ }): FFOAuth2Provider<GitHub, 'github'>;
@@ -1,9 +1,8 @@
1
1
  import { GitHub } from 'arctic';
2
2
  import { remult } from 'remult';
3
3
  import { env } from '$env/dynamic/private';
4
- import { checkOAuthConfig } from '.';
5
- import {} from '../';
6
- import { logAuth } from '../client';
4
+ import { authModuleRaw, } from '../module';
5
+ import { checkOAuthConfig } from './helperProvider';
7
6
  //------------------------------
8
7
  // For developers (future me ?), To do another OAuth2 provider:
9
8
  // Replace GITHUB / Github / github
@@ -15,7 +14,7 @@ import { logAuth } from '../client';
15
14
  *
16
15
  * 1. Get your **id** & **secret** from [GitHub (direct link)](https://github.com/settings/developers).
17
16
  * 2. In GitHub, set your callback url to
18
- * - [ ] dev: `http://localhost:5173/api/auth_callback`
17
+ * - [ ] dev: `http://_YOUR_LOCAL_URL:PORT_/api/auth_callback`
19
18
  * - [ ] prod: `https://MY_SUPER_SITE/api/auth_callback`
20
19
  * 3. In your project add a `.env` file with the following:
21
20
  * ```bash
@@ -39,28 +38,38 @@ export function github(options) {
39
38
  checkOAuthConfig(name, clientID, secret, urlForKeys, false);
40
39
  return {
41
40
  name,
42
- isPKCE: false,
43
41
  getArcticProvider: () => {
44
42
  const redirectURI = options?.GITHUB_REDIRECT_URI ??
45
43
  env.GITHUB_REDIRECT_URI ??
46
- `${remult.context.url.origin}/api/auth_callback`;
44
+ `${remult.context.request.url.origin}/api/auth_callback`;
47
45
  checkOAuthConfig(name, clientID, secret, urlForKeys, true);
48
- return new GitHub(clientID, secret, { redirectURI });
46
+ const o = new GitHub(clientID, secret, redirectURI);
47
+ return o;
49
48
  },
50
49
  authorizationURLOptions: () => {
51
- return options?.authorizationURLOptions ?? { scopes: [] };
52
- },
53
- getUserInfo: async (tokens) => {
54
- const res = await fetch('https://api.github.com/user', {
55
- headers: {
56
- Authorization: `Bearer ${tokens.accessToken}`,
57
- },
58
- });
59
- const user = await res.json();
60
- if (options?.log) {
61
- logAuth.info(`user`, user);
62
- }
63
- return { raw: user, providerUserId: String(user.id), nameOptions: [user.login] };
50
+ return options?.authorizationURLOptions ?? [];
64
51
  },
52
+ getUserInfo: options?.getUserInfo
53
+ ? options.getUserInfo
54
+ : async (tokens) => {
55
+ const res = await fetch('https://api.github.com/user', {
56
+ headers: {
57
+ Authorization: `Bearer ${tokens.accessToken()}`,
58
+ },
59
+ });
60
+ const user = await res.json();
61
+ if ((options?.authorizationURLOptions ?? []).includes('user:email')) {
62
+ const res = await fetch('https://api.github.com/user/emails', {
63
+ headers: {
64
+ Authorization: `Bearer ${tokens.accessToken()}`,
65
+ },
66
+ });
67
+ user.emails = await res.json();
68
+ }
69
+ if (options?.log) {
70
+ authModuleRaw.log.info(`user`, user);
71
+ }
72
+ return { raw: user, providerUserId: String(user.id), nameOptions: [user.login] };
73
+ },
65
74
  };
66
75
  }
@@ -1,3 +1 @@
1
1
  export declare const checkOAuthConfig: (name: string, clientId: string, secret: string, urlForKeys: string, withThrow: boolean) => void;
2
- export { github } from './github';
3
- export { strava } from './strava';
@@ -1,6 +1,7 @@
1
+ import { EntityError } from 'remult';
1
2
  import { cyan, gray, green, italic, yellow } from '@kitql/helpers';
2
- import { mask } from '../../formats/strings';
3
- import { logAuth } from '../client';
3
+ import { mask } from '../../../formats/strings';
4
+ import { authModuleRaw } from '../module';
4
5
  export const checkOAuthConfig = (name, clientId, secret, urlForKeys, withThrow) => {
5
6
  if (!clientId || !secret) {
6
7
  const msg = `Wrong configuration for ${green(name)} provider.
@@ -15,12 +16,10 @@ export const checkOAuthConfig = (name, clientId, secret, urlForKeys, withThrow)
15
16
  Check ${cyan(urlForKeys)} to generate your keys.
16
17
  `;
17
18
  if (withThrow) {
18
- throw new Error(msg);
19
+ throw new EntityError({ message: msg });
19
20
  }
20
21
  else {
21
- logAuth.error(msg);
22
+ authModuleRaw.log.error(msg);
22
23
  }
23
24
  }
24
25
  };
25
- export { github } from './github';
26
- export { strava } from './strava';
@@ -0,0 +1,5 @@
1
+ export { Ml as default };
2
+ declare class Ml extends st {
3
+ constructor(e: any);
4
+ }
5
+ import { S as st } from "./index-D-Ztdt2o.js";