@appweaver/core 1.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.
Files changed (271) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +7 -0
  3. package/app/application.d.ts +43 -0
  4. package/app/application.js +112 -0
  5. package/app/create-app.d.ts +32 -0
  6. package/app/create-app.js +38 -0
  7. package/app/index.d.ts +2 -0
  8. package/app/index.js +18 -0
  9. package/app/lifecycle-manager.d.ts +20 -0
  10. package/app/lifecycle-manager.js +42 -0
  11. package/app/load-modules.d.ts +10 -0
  12. package/app/load-modules.js +50 -0
  13. package/app/load-providers.d.ts +8 -0
  14. package/app/load-providers.js +33 -0
  15. package/cache/cache-service.d.ts +72 -0
  16. package/cache/cache-service.js +202 -0
  17. package/cache/cache.d.ts +12 -0
  18. package/cache/cache.js +184 -0
  19. package/cache/caching.d.ts +8 -0
  20. package/cache/caching.js +72 -0
  21. package/cache/eviction/eviction-index.d.ts +35 -0
  22. package/cache/eviction/eviction-index.js +2 -0
  23. package/cache/eviction/fifo-eviction-index.d.ts +7 -0
  24. package/cache/eviction/fifo-eviction-index.js +28 -0
  25. package/cache/eviction/index.d.ts +4 -0
  26. package/cache/eviction/index.js +20 -0
  27. package/cache/eviction/lfu-eviction-index.d.ts +8 -0
  28. package/cache/eviction/lfu-eviction-index.js +82 -0
  29. package/cache/eviction/lru-eviction-index.d.ts +8 -0
  30. package/cache/eviction/lru-eviction-index.js +81 -0
  31. package/cache/index.d.ts +2 -0
  32. package/cache/index.js +18 -0
  33. package/cache/memory-cache.d.ts +4 -0
  34. package/cache/memory-cache.js +12 -0
  35. package/cache/redis-cache.d.ts +4 -0
  36. package/cache/redis-cache.js +12 -0
  37. package/context/context.d.ts +2 -0
  38. package/context/context.js +13 -0
  39. package/context/dependency-injection.d.ts +98 -0
  40. package/context/dependency-injection.js +276 -0
  41. package/context/index.d.ts +2 -0
  42. package/context/index.js +18 -0
  43. package/database/create-client.d.ts +11 -0
  44. package/database/create-client.js +142 -0
  45. package/database/index.d.ts +1 -0
  46. package/database/index.js +17 -0
  47. package/database/prisma-database.d.ts +15 -0
  48. package/database/prisma-database.js +53 -0
  49. package/errors/error-handler.d.ts +3 -0
  50. package/errors/error-handler.js +24 -0
  51. package/errors/error-schema.d.ts +32 -0
  52. package/errors/error-schema.js +31 -0
  53. package/errors/http-error.d.ts +21 -0
  54. package/errors/http-error.js +33 -0
  55. package/errors/index.d.ts +3 -0
  56. package/errors/index.js +19 -0
  57. package/events/node-events.d.ts +7 -0
  58. package/events/node-events.js +39 -0
  59. package/export/export-service.d.ts +19 -0
  60. package/export/export-service.js +154 -0
  61. package/export/index.d.ts +1 -0
  62. package/export/index.js +17 -0
  63. package/factory/create-model.d.ts +2 -0
  64. package/factory/create-model.js +366 -0
  65. package/factory/create-policy.d.ts +2 -0
  66. package/factory/create-policy.js +16 -0
  67. package/factory/create-routes.d.ts +2 -0
  68. package/factory/create-routes.js +21 -0
  69. package/factory/create-service.d.ts +3 -0
  70. package/factory/create-service.js +97 -0
  71. package/factory/index.d.ts +4 -0
  72. package/factory/index.js +20 -0
  73. package/health/health-routes.d.ts +2 -0
  74. package/health/health-routes.js +36 -0
  75. package/health/health-schema.d.ts +45 -0
  76. package/health/health-schema.js +52 -0
  77. package/health/health-service.d.ts +38 -0
  78. package/health/health-service.js +82 -0
  79. package/health/index.d.ts +2 -0
  80. package/health/index.js +18 -0
  81. package/index.d.ts +15 -0
  82. package/index.js +31 -0
  83. package/mailer/email-service.d.ts +36 -0
  84. package/mailer/email-service.js +89 -0
  85. package/mailer/index.d.ts +1 -0
  86. package/mailer/index.js +17 -0
  87. package/mailer/json-mailer.d.ts +7 -0
  88. package/mailer/json-mailer.js +32 -0
  89. package/mailer/smtp-mailer.d.ts +7 -0
  90. package/mailer/smtp-mailer.js +43 -0
  91. package/memory/in-memory.d.ts +24 -0
  92. package/memory/in-memory.js +164 -0
  93. package/memory/redis.d.ts +26 -0
  94. package/memory/redis.js +158 -0
  95. package/package.json +68 -0
  96. package/prisma/client/browser.d.ts +34 -0
  97. package/prisma/client/browser.js +56 -0
  98. package/prisma/client/client.d.ts +53 -0
  99. package/prisma/client/client.js +70 -0
  100. package/prisma/client/commonInputTypes.d.ts +395 -0
  101. package/prisma/client/commonInputTypes.js +11 -0
  102. package/prisma/client/enums.d.ts +1 -0
  103. package/prisma/client/enums.js +11 -0
  104. package/prisma/client/internal/class.d.ts +187 -0
  105. package/prisma/client/internal/class.js +85 -0
  106. package/prisma/client/internal/prismaNamespace.d.ts +987 -0
  107. package/prisma/client/internal/prismaNamespace.js +193 -0
  108. package/prisma/client/internal/prismaNamespaceBrowser.d.ts +125 -0
  109. package/prisma/client/internal/prismaNamespaceBrowser.js +164 -0
  110. package/prisma/client/models/ApiKey.d.ts +1167 -0
  111. package/prisma/client/models/ApiKey.js +2 -0
  112. package/prisma/client/models/File.d.ts +1248 -0
  113. package/prisma/client/models/File.js +2 -0
  114. package/prisma/client/models/OneTimeToken.d.ts +1083 -0
  115. package/prisma/client/models/OneTimeToken.js +2 -0
  116. package/prisma/client/models/Permission.d.ts +1209 -0
  117. package/prisma/client/models/Permission.js +2 -0
  118. package/prisma/client/models/Role.d.ts +1209 -0
  119. package/prisma/client/models/Role.js +2 -0
  120. package/prisma/client/models/Seeder.d.ts +1023 -0
  121. package/prisma/client/models/Seeder.js +2 -0
  122. package/prisma/client/models.d.ts +7 -0
  123. package/prisma/client/models.js +2 -0
  124. package/queue/bull-queue.d.ts +37 -0
  125. package/queue/bull-queue.js +207 -0
  126. package/queue/memory-queue.d.ts +54 -0
  127. package/queue/memory-queue.js +283 -0
  128. package/resource/index.d.ts +4 -0
  129. package/resource/index.js +20 -0
  130. package/resource/resource-loader.d.ts +26 -0
  131. package/resource/resource-loader.js +161 -0
  132. package/resource/resource-routes.d.ts +3 -0
  133. package/resource/resource-routes.js +174 -0
  134. package/resource/resource-schema.d.ts +33 -0
  135. package/resource/resource-schema.js +186 -0
  136. package/resource/resource-service.d.ts +89 -0
  137. package/resource/resource-service.js +772 -0
  138. package/resources.d.ts +9 -0
  139. package/resources.js +24 -0
  140. package/scheduler/cron-scheduler.d.ts +12 -0
  141. package/scheduler/cron-scheduler.js +73 -0
  142. package/security/account/account-routes.d.ts +2 -0
  143. package/security/account/account-routes.js +104 -0
  144. package/security/account/account-schema.d.ts +290 -0
  145. package/security/account/account-schema.js +166 -0
  146. package/security/account/account-service.d.ts +88 -0
  147. package/security/account/account-service.js +218 -0
  148. package/security/account/index.d.ts +3 -0
  149. package/security/account/index.js +19 -0
  150. package/security/api-key/api-key-auth.d.ts +4 -0
  151. package/security/api-key/api-key-auth.js +66 -0
  152. package/security/api-key/index.d.ts +1 -0
  153. package/security/api-key/index.js +17 -0
  154. package/security/auth-routes.d.ts +2 -0
  155. package/security/auth-routes.js +80 -0
  156. package/security/auth-schema.d.ts +215 -0
  157. package/security/auth-schema.js +129 -0
  158. package/security/auth-service.d.ts +117 -0
  159. package/security/auth-service.js +272 -0
  160. package/security/auth.d.ts +3 -0
  161. package/security/auth.js +127 -0
  162. package/security/basic/basic-auth.d.ts +4 -0
  163. package/security/basic/basic-auth.js +32 -0
  164. package/security/basic/index.d.ts +1 -0
  165. package/security/basic/index.js +17 -0
  166. package/security/create-auth-resources.d.ts +6 -0
  167. package/security/create-auth-resources.js +129 -0
  168. package/security/helper.d.ts +127 -0
  169. package/security/helper.js +329 -0
  170. package/security/index.d.ts +4 -0
  171. package/security/index.js +20 -0
  172. package/security/jwt/index.d.ts +2 -0
  173. package/security/jwt/index.js +18 -0
  174. package/security/jwt/jwt-auth.d.ts +4 -0
  175. package/security/jwt/jwt-auth.js +57 -0
  176. package/security/jwt/jwt-keys.d.ts +7 -0
  177. package/security/jwt/jwt-keys.js +43 -0
  178. package/security/oauth2/create-oauth2-plugin.d.ts +17 -0
  179. package/security/oauth2/create-oauth2-plugin.js +85 -0
  180. package/security/oauth2/index.d.ts +3 -0
  181. package/security/oauth2/index.js +19 -0
  182. package/security/oauth2/oauth2-custom.d.ts +7 -0
  183. package/security/oauth2/oauth2-custom.js +40 -0
  184. package/security/oauth2/oauth2-facebook.d.ts +1 -0
  185. package/security/oauth2/oauth2-facebook.js +30 -0
  186. package/security/oauth2/oauth2-google.d.ts +1 -0
  187. package/security/oauth2/oauth2-google.js +28 -0
  188. package/security/oauth2/oauth2-schema.d.ts +10 -0
  189. package/security/oauth2/oauth2-schema.js +53 -0
  190. package/security/recaptcha/index.d.ts +2 -0
  191. package/security/recaptcha/index.js +18 -0
  192. package/security/recaptcha/recaptcha-verify.d.ts +1 -0
  193. package/security/recaptcha/recaptcha-verify.js +33 -0
  194. package/security/recaptcha/recaptcha.d.ts +2 -0
  195. package/security/recaptcha/recaptcha.js +22 -0
  196. package/security/resources/api-key/model.d.ts +2 -0
  197. package/security/resources/api-key/model.js +63 -0
  198. package/security/resources/api-key/policy.d.ts +2 -0
  199. package/security/resources/api-key/policy.js +26 -0
  200. package/security/resources/api-key/routes.d.ts +2 -0
  201. package/security/resources/api-key/routes.js +15 -0
  202. package/security/resources/api-key/service.d.ts +3 -0
  203. package/security/resources/api-key/service.js +33 -0
  204. package/security/resources/one-time-token/model.d.ts +2 -0
  205. package/security/resources/one-time-token/model.js +32 -0
  206. package/security/resources/permission/model.d.ts +2 -0
  207. package/security/resources/permission/model.js +16 -0
  208. package/security/resources/role/model.d.ts +2 -0
  209. package/security/resources/role/model.js +22 -0
  210. package/security/store/database-security-store.d.ts +5 -0
  211. package/security/store/database-security-store.js +51 -0
  212. package/security/store/redis-security-store.d.ts +5 -0
  213. package/security/store/redis-security-store.js +32 -0
  214. package/seeder/create-seeder.d.ts +21 -0
  215. package/seeder/create-seeder.js +17 -0
  216. package/seeder/index.d.ts +2 -0
  217. package/seeder/index.js +18 -0
  218. package/seeder/resources/seeder/model.d.ts +2 -0
  219. package/seeder/resources/seeder/model.js +38 -0
  220. package/seeder/seeder.d.ts +20 -0
  221. package/seeder/seeder.js +175 -0
  222. package/server/create-server.d.ts +20 -0
  223. package/server/create-server.js +160 -0
  224. package/server/index.d.ts +4 -0
  225. package/server/index.js +20 -0
  226. package/server/info-route.d.ts +2 -0
  227. package/server/info-route.js +18 -0
  228. package/server/info-schema.d.ts +37 -0
  229. package/server/info-schema.js +19 -0
  230. package/server/register-model.d.ts +2 -0
  231. package/server/register-model.js +12 -0
  232. package/server/register-plugin.d.ts +2 -0
  233. package/server/register-plugin.js +13 -0
  234. package/server/register-route.d.ts +3 -0
  235. package/server/register-route.js +74 -0
  236. package/server/schemas.d.ts +3 -0
  237. package/server/schemas.js +30 -0
  238. package/server/swagger.d.ts +3 -0
  239. package/server/swagger.js +122 -0
  240. package/storage/file-route.d.ts +2 -0
  241. package/storage/file-route.js +39 -0
  242. package/storage/file-schema.d.ts +9 -0
  243. package/storage/file-schema.js +42 -0
  244. package/storage/file-service.d.ts +81 -0
  245. package/storage/file-service.js +384 -0
  246. package/storage/filesystem-storage.d.ts +10 -0
  247. package/storage/filesystem-storage.js +128 -0
  248. package/storage/index.d.ts +2 -0
  249. package/storage/index.js +18 -0
  250. package/storage/resources/file/model.d.ts +2 -0
  251. package/storage/resources/file/model.js +75 -0
  252. package/types/application-context.d.ts +20 -0
  253. package/types/application-context.js +2 -0
  254. package/types/auth.d.ts +31 -0
  255. package/types/auth.js +2 -0
  256. package/types/fastify-extensions.d.ts +24 -0
  257. package/types/fastify-extensions.js +4 -0
  258. package/types/generated.d.ts +193 -0
  259. package/types/generated.js +3 -0
  260. package/types/index.d.ts +4 -0
  261. package/types/index.js +20 -0
  262. package/types/server.d.ts +4 -0
  263. package/types/server.js +2 -0
  264. package/utils/export-util.d.ts +8 -0
  265. package/utils/export-util.js +25 -0
  266. package/utils/file-util.d.ts +64 -0
  267. package/utils/file-util.js +141 -0
  268. package/utils/index.d.ts +3 -0
  269. package/utils/index.js +19 -0
  270. package/utils/schema-util.d.ts +20 -0
  271. package/utils/schema-util.js +37 -0
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createOAuth2Plugin = createOAuth2Plugin;
7
+ const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
8
+ const oauth2_1 = __importDefault(require("@fastify/oauth2"));
9
+ const common_1 = require("@appweaver/common");
10
+ const context_1 = require("../../context");
11
+ const errors_1 = require("../../errors");
12
+ const auth_service_1 = require("../auth-service");
13
+ const helper_1 = require("../helper");
14
+ const oauth2_schema_1 = require("./oauth2-schema");
15
+ function createOAuth2Plugin(authSource, oAuth2Config) {
16
+ const name = authSource.replace('oauth2', '');
17
+ const upperName = name.toUpperCase();
18
+ const lowerName = name.toLowerCase();
19
+ return (0, fastify_plugin_1.default)(async (server) => {
20
+ if (!oAuth2Config.enabled) {
21
+ return;
22
+ }
23
+ if (!oAuth2Config.clientId || !oAuth2Config.clientSecret) {
24
+ throw Error(`${name} OAuth2 configuration is missing`);
25
+ }
26
+ if (server[authSource] !== undefined) {
27
+ throw Error(`${name} OAuth2 provider is already registered`);
28
+ }
29
+ const authConfig = oauth2_1.default[`${upperName}_CONFIGURATION`];
30
+ if (!authConfig && !oAuth2Config.issuer) {
31
+ throw Error(`${name} OAuth2 provider is not supported`);
32
+ }
33
+ const authService = (0, context_1.inject)(auth_service_1.AuthService);
34
+ const securityStore = (0, context_1.inject)(common_1.SecurityStore);
35
+ const prefix = common_1.config.SECURITY_ROUTE_PREFIX.replace(/\/$/, '');
36
+ server.register(oauth2_1.default, {
37
+ name: authSource,
38
+ credentials: {
39
+ client: {
40
+ id: oAuth2Config.clientId,
41
+ secret: oAuth2Config.clientSecret
42
+ },
43
+ auth: authConfig
44
+ },
45
+ ...(oAuth2Config.issuer
46
+ ? { discovery: { issuer: oAuth2Config.issuer } }
47
+ : {}),
48
+ scope: oAuth2Config.scope,
49
+ schema: (0, oauth2_schema_1.createOAuth2RedirectSchema)(name),
50
+ startRedirectPath: `${prefix}/login/${lowerName}`,
51
+ callbackUri: `${common_1.config.APP_HOSTNAME}${prefix}/login/${lowerName}/callback`,
52
+ generateStateFunction: async (request) => {
53
+ const redirectToUrl = request.query.redirectToUrl;
54
+ const result = (0, helper_1.validateRedirectUrl)(redirectToUrl);
55
+ if (!result.valid) {
56
+ throw new errors_1.HttpError(result.message, 400);
57
+ }
58
+ return securityStore.generateOneTimeToken(common_1.AuthOTTPurpose.OAuth2State, { redirectToUrl }, common_1.config.SECURITY_OAUTH2_STATE_TTL);
59
+ },
60
+ checkStateFunction: async (request) => {
61
+ const state = request.query.state;
62
+ request.oauth2State =
63
+ await securityStore.useOneTimeToken(state, common_1.AuthOTTPurpose.OAuth2State);
64
+ return true;
65
+ }
66
+ });
67
+ server.get(`${prefix}/login/${lowerName}/callback`, {
68
+ schema: (0, oauth2_schema_1.createOAuth2CallbackSchema)(name)
69
+ }, async function (request, reply) {
70
+ const { token } = await server[authSource].getAccessTokenFromAuthorizationCodeFlow(request);
71
+ const userInfo = await oAuth2Config.extractUserInfo(token.access_token);
72
+ let authUser = await authService.findByUsername(userInfo.email);
73
+ if (!authUser) {
74
+ authUser = await authService.registerAuthUser(authSource, userInfo.email, undefined, (0, common_1.pickProperties)(userInfo, ['firstName', 'lastName']));
75
+ }
76
+ else if (!authUser.verifiedEmail) {
77
+ throw new errors_1.HttpError('Auth user email address is not verified', 403);
78
+ }
79
+ const stateData = request.oauth2State;
80
+ const ott = await securityStore.generateOneTimeToken(common_1.AuthOTTPurpose.Authentication, { authUserId: authUser.id, authSource }, common_1.config.SECURITY_AUTH_OTT_TTL);
81
+ const separator = stateData.redirectToUrl.includes('?') ? '&' : '?';
82
+ return reply.redirect(`${stateData.redirectToUrl}${separator}token=${ott}`);
83
+ });
84
+ });
85
+ }
@@ -0,0 +1,3 @@
1
+ export * from './oauth2-custom';
2
+ export * from './oauth2-facebook';
3
+ export * from './oauth2-google';
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./oauth2-custom"), exports);
18
+ __exportStar(require("./oauth2-facebook"), exports);
19
+ __exportStar(require("./oauth2-google"), exports);
@@ -0,0 +1,7 @@
1
+ export type OAuth2UserInfo = {
2
+ sub: string;
3
+ email: string;
4
+ given_name: string;
5
+ family_name: string;
6
+ };
7
+ export declare const oauth2Custom: (server: import("../..").Server) => Promise<void>;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.oauth2Custom = void 0;
4
+ const common_1 = require("@appweaver/common");
5
+ const context_1 = require("../../context");
6
+ const errors_1 = require("../../errors");
7
+ const create_oauth2_plugin_1 = require("./create-oauth2-plugin");
8
+ exports.oauth2Custom = (0, create_oauth2_plugin_1.createOAuth2Plugin)(common_1.AuthSource.OAuth2Custom, {
9
+ enabled: common_1.config.SECURITY_OAUTH2_CUSTOM_ENABLED,
10
+ clientId: common_1.config.SECURITY_OAUTH2_CUSTOM_CLIENT_ID,
11
+ clientSecret: common_1.config.SECURITY_OAUTH2_CUSTOM_CLIENT_SECRET,
12
+ issuer: common_1.config.SECURITY_OAUTH2_CUSTOM_ISSUER,
13
+ scope: ['openid', 'profile', 'email'],
14
+ extractUserInfo: (accessToken) => fetchCustomUser(accessToken)
15
+ });
16
+ async function fetchCustomUser(accessToken) {
17
+ const server = context_1.context.server;
18
+ if (!server) {
19
+ throw new errors_1.HttpError('Server is not available', 500);
20
+ }
21
+ const customOauth2 = server[common_1.AuthSource.OAuth2Custom];
22
+ let data;
23
+ if (typeof customOauth2?.userinfo === 'function') {
24
+ data = (await customOauth2.userinfo(accessToken));
25
+ }
26
+ else {
27
+ // Fallback to direct API call if the plugin is not initialized
28
+ const resp = await fetch(`${common_1.config.SECURITY_OAUTH2_CUSTOM_ISSUER}/protocol/openid-connect/userinfo`, { method: 'GET', headers: { authorization: `Bearer ${accessToken}` } });
29
+ if (!resp.ok) {
30
+ throw new errors_1.HttpError(`Custom OAuth2 API error: ${resp.status} ${resp.statusText}`, 500);
31
+ }
32
+ data = await resp.json();
33
+ }
34
+ return {
35
+ id: data.sub,
36
+ email: data.email,
37
+ firstName: data.given_name,
38
+ lastName: data.family_name
39
+ };
40
+ }
@@ -0,0 +1 @@
1
+ export declare const oauth2Facebook: (server: import("../..").Server) => Promise<void>;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.oauth2Facebook = void 0;
4
+ const common_1 = require("@appweaver/common");
5
+ const errors_1 = require("../../errors");
6
+ const create_oauth2_plugin_1 = require("./create-oauth2-plugin");
7
+ exports.oauth2Facebook = (0, create_oauth2_plugin_1.createOAuth2Plugin)(common_1.AuthSource.OAuth2Facebook, {
8
+ enabled: common_1.config.SECURITY_OAUTH2_FACEBOOK_ENABLED,
9
+ clientId: common_1.config.SECURITY_OAUTH2_FACEBOOK_CLIENT_ID,
10
+ clientSecret: common_1.config.SECURITY_OAUTH2_FACEBOOK_CLIENT_SECRET,
11
+ scope: ['public_profile', 'email'],
12
+ extractUserInfo: (accessToken) => fetchFacebookUser(accessToken)
13
+ });
14
+ async function fetchFacebookUser(accessToken) {
15
+ const params = new URLSearchParams();
16
+ params.append('fields', 'id,name,email');
17
+ params.append('access_token', accessToken);
18
+ const resp = await fetch(`${common_1.config.SECURITY_OAUTH2_FACEBOOK_USER_INFO_URL}?${params}`, { method: 'GET' });
19
+ if (!resp.ok) {
20
+ throw new errors_1.HttpError(`Facebook Graph API error: ${resp.status} ${resp.statusText}`, 500);
21
+ }
22
+ const data = await resp.json();
23
+ const [firstName, lastName] = data.name.split(' ');
24
+ return {
25
+ id: data.id,
26
+ email: data.email,
27
+ firstName,
28
+ lastName
29
+ };
30
+ }
@@ -0,0 +1 @@
1
+ export declare const oauth2Google: (server: import("../..").Server) => Promise<void>;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.oauth2Google = void 0;
4
+ const common_1 = require("@appweaver/common");
5
+ const errors_1 = require("../../errors");
6
+ const create_oauth2_plugin_1 = require("./create-oauth2-plugin");
7
+ exports.oauth2Google = (0, create_oauth2_plugin_1.createOAuth2Plugin)(common_1.AuthSource.OAuth2Google, {
8
+ enabled: common_1.config.SECURITY_OAUTH2_GOOGLE_ENABLED,
9
+ clientId: common_1.config.SECURITY_OAUTH2_GOOGLE_CLIENT_ID,
10
+ clientSecret: common_1.config.SECURITY_OAUTH2_GOOGLE_CLIENT_SECRET,
11
+ scope: ['profile', 'email'],
12
+ extractUserInfo: (accessToken) => fetchGoogleUser(accessToken)
13
+ });
14
+ async function fetchGoogleUser(accessToken) {
15
+ const params = new URLSearchParams();
16
+ params.append('access_token', accessToken);
17
+ const resp = await fetch(`${common_1.config.SECURITY_OAUTH2_GOOGLE_USER_INFO_URL}?${params}`, { method: 'GET' });
18
+ if (!resp.ok) {
19
+ throw new errors_1.HttpError(`Google API error: ${resp.status} ${resp.statusText}`, 500);
20
+ }
21
+ const data = await resp.json();
22
+ return {
23
+ id: data.id,
24
+ email: data.email,
25
+ firstName: data.given_name,
26
+ lastName: data.family_name
27
+ };
28
+ }
@@ -0,0 +1,10 @@
1
+ import { RouteSchema } from '@appweaver/common';
2
+ export declare const OAuth2RedirectQuery: import("@sinclair/typebox").TObject<{
3
+ redirectToUrl: import("@sinclair/typebox").TString;
4
+ }>;
5
+ export declare const OAuth2CallbackQuery: import("@sinclair/typebox").TObject<{
6
+ code: import("@sinclair/typebox").TString;
7
+ state: import("@sinclair/typebox").TString;
8
+ }>;
9
+ export declare function createOAuth2RedirectSchema(providerName: string): RouteSchema;
10
+ export declare function createOAuth2CallbackSchema(providerName: string): RouteSchema;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OAuth2CallbackQuery = exports.OAuth2RedirectQuery = void 0;
4
+ exports.createOAuth2RedirectSchema = createOAuth2RedirectSchema;
5
+ exports.createOAuth2CallbackSchema = createOAuth2CallbackSchema;
6
+ const typebox_1 = require("@sinclair/typebox");
7
+ const errors_1 = require("../../errors");
8
+ exports.OAuth2RedirectQuery = typebox_1.Type.Object({
9
+ redirectToUrl: typebox_1.Type.String({
10
+ format: 'uri',
11
+ description: 'A URL to redirect to with one-time-token after successful' +
12
+ ' authentication. The client then needs to exchange this token for' +
13
+ ' an JWT access token',
14
+ example: 'https://example.com/login/handler'
15
+ })
16
+ });
17
+ exports.OAuth2CallbackQuery = typebox_1.Type.Object({
18
+ code: typebox_1.Type.String({
19
+ description: 'Authorization code from OAuth2 provider',
20
+ example: '3b7bdc9982feac0e20cf4ddc9be52a1a027142e25b4d14c1b5a280595bc20'
21
+ }),
22
+ state: typebox_1.Type.String({
23
+ description: 'Authorization state returned from OAuth2 provider',
24
+ example: '89bbb34d76801fcf8251193a02a1d62c7c87a'
25
+ })
26
+ });
27
+ function createOAuth2RedirectSchema(providerName) {
28
+ return {
29
+ tags: ['Auth'],
30
+ summary: `Redirect to ${providerName} authentication page`,
31
+ description: `Redirect to ${providerName} authentication page`,
32
+ querystring: exports.OAuth2RedirectQuery,
33
+ response: {
34
+ 302: {
35
+ description: `Redirect to ${providerName} authentication page`
36
+ }
37
+ }
38
+ };
39
+ }
40
+ function createOAuth2CallbackSchema(providerName) {
41
+ return {
42
+ tags: ['Auth'],
43
+ summary: `Authenticate identity from ${providerName} callback`,
44
+ description: `Authenticate identity from ${providerName} callback`,
45
+ querystring: exports.OAuth2CallbackQuery,
46
+ response: {
47
+ 302: {
48
+ description: `Redirect to 'redirectToUrl' provided when initiating OAuth2 authentication`
49
+ },
50
+ ...errors_1.AllErrorResponses
51
+ }
52
+ };
53
+ }
@@ -0,0 +1,2 @@
1
+ export * from './recaptcha';
2
+ export * from './recaptcha-verify';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./recaptcha"), exports);
18
+ __exportStar(require("./recaptcha-verify"), exports);
@@ -0,0 +1 @@
1
+ export declare function recaptchaVerify(token: string, remoteIp?: string, action?: string): Promise<void>;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.recaptchaVerify = recaptchaVerify;
4
+ const common_1 = require("@appweaver/common");
5
+ const errors_1 = require("../../errors");
6
+ async function recaptchaVerify(token, remoteIp, action) {
7
+ const params = new URLSearchParams();
8
+ params.set('secret', common_1.config.SECURITY_RECAPTCHA_SECRET);
9
+ params.set('response', token);
10
+ if (remoteIp) {
11
+ params.set('remoteip', remoteIp);
12
+ }
13
+ const resp = await fetch(common_1.config.SECURITY_RECAPTCHA_VERIFY_URL, {
14
+ method: 'POST',
15
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
16
+ body: params.toString()
17
+ });
18
+ if (!resp.ok) {
19
+ common_1.logger.error(`reCAPTCHA request failed: ${resp.statusText}`);
20
+ throw new errors_1.HttpError('reCAPTCHA request failed', 500);
21
+ }
22
+ const data = await resp.json();
23
+ common_1.logger.debug(data, 'reCAPTCHA verified');
24
+ if (!data.success) {
25
+ throw new errors_1.HttpError('reCAPTCHA invalid token', 400);
26
+ }
27
+ if (action && data.action !== action) {
28
+ throw new errors_1.HttpError('reCAPTCHA action mismatch', 403);
29
+ }
30
+ if (data.score < common_1.config.SECURITY_RECAPTCHA_MIN_SCORE) {
31
+ throw new errors_1.HttpError('reCAPTCHA low score', 403);
32
+ }
33
+ }
@@ -0,0 +1,2 @@
1
+ import { Server } from '../../types';
2
+ export declare const recaptcha: (server: Server) => Promise<void>;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.recaptcha = void 0;
7
+ const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
8
+ const common_1 = require("@appweaver/common");
9
+ const errors_1 = require("../../errors");
10
+ const recaptcha_verify_1 = require("./recaptcha-verify");
11
+ exports.recaptcha = (0, fastify_plugin_1.default)(async (server) => {
12
+ if (!common_1.config.SECURITY_RECAPTCHA_SECRET) {
13
+ throw Error('reCAPTCHA secret is not set');
14
+ }
15
+ server.decorate('recaptcha', async (request) => {
16
+ const token = request.headers[common_1.config.SECURITY_RECAPTCHA_HEADER_NAME.toLowerCase()];
17
+ if (!token) {
18
+ throw new errors_1.HttpError(`Missing reCAPTCHA header: ${common_1.config.SECURITY_RECAPTCHA_HEADER_NAME}`, 401);
19
+ }
20
+ await (0, recaptcha_verify_1.recaptchaVerify)(String(token).trim(), request.ip, request.routeOptions.config.recaptchaAction);
21
+ });
22
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@appweaver/common").ResourceModel | undefined;
2
+ export default _default;
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const common_1 = require("@appweaver/common");
4
+ const factory_1 = require("../../../factory");
5
+ const helper_1 = require("../../helper");
6
+ const authModel = (0, helper_1.resourceAuthModel)();
7
+ const shouldCreateModel = common_1.config.SECURITY_API_KEY_ENABLED ||
8
+ common_1.config.SECURITY_API_KEY_KEEP_DATABASE_TABLE;
9
+ exports.default = shouldCreateModel
10
+ ? (0, factory_1.createModel)({
11
+ name: 'ApiKey',
12
+ scalars: {
13
+ key: {
14
+ type: 'string'
15
+ },
16
+ keyHash: {
17
+ type: 'string',
18
+ unique: true,
19
+ hidden: true
20
+ },
21
+ name: {
22
+ type: 'string',
23
+ required: false,
24
+ maxLength: 255
25
+ },
26
+ description: {
27
+ type: 'string',
28
+ required: false
29
+ },
30
+ enabled: {
31
+ type: 'boolean',
32
+ default: true
33
+ },
34
+ expiresAt: {
35
+ type: 'dateTime',
36
+ required: false
37
+ }
38
+ },
39
+ ...(authModel
40
+ ? {
41
+ relations: {
42
+ [(0, common_1.uncapitalize)(authModel.name)]: {
43
+ model: authModel.name,
44
+ mappedBy: 'apiKeys',
45
+ owner: true,
46
+ input: {
47
+ type: 'none'
48
+ },
49
+ output: {
50
+ type: 'none'
51
+ }
52
+ }
53
+ }
54
+ }
55
+ : {}),
56
+ create: {
57
+ omit: ['key']
58
+ },
59
+ update: {
60
+ omit: ['key', 'expiresAt']
61
+ }
62
+ })
63
+ : undefined;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@appweaver/common").ResourcePolicyConfig<any> | undefined;
2
+ export default _default;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const common_1 = require("@appweaver/common");
4
+ const factory_1 = require("../../../factory");
5
+ const helper_1 = require("../../helper");
6
+ function authModelField() {
7
+ return (0, common_1.uncapitalize)((0, helper_1.resourceAuthModel)().name);
8
+ }
9
+ exports.default = common_1.config.SECURITY_API_KEY_ENABLED
10
+ ? (0, factory_1.createPolicy)({
11
+ modelName: 'ApiKey',
12
+ checkAccess: (action, resource) => {
13
+ const authFieldName = authModelField();
14
+ const currentAuthId = (0, helper_1.currentAuthUser)().id;
15
+ if (action === 'create') {
16
+ return resource[authFieldName].id === currentAuthId;
17
+ }
18
+ else {
19
+ return resource[`${authFieldName}Id`] === currentAuthId;
20
+ }
21
+ },
22
+ readRestrictions: () => {
23
+ return { [authModelField()]: { id: (0, helper_1.currentAuthUser)().id } };
24
+ }
25
+ })
26
+ : undefined;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@appweaver/common").ResourceRoutes | undefined;
2
+ export default _default;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const common_1 = require("@appweaver/common");
4
+ const factory_1 = require("../../../factory");
5
+ exports.default = common_1.config.SECURITY_API_KEY_ENABLED
6
+ ? (0, factory_1.createRoutes)({
7
+ modelName: 'ApiKey',
8
+ aggregate: {
9
+ exclude: true
10
+ },
11
+ export: {
12
+ exclude: true
13
+ }
14
+ })
15
+ : undefined;
@@ -0,0 +1,3 @@
1
+ import { ApiKey } from '../../../types';
2
+ declare const _default: import("@appweaver/common").Ctor<import("../../..").ResourceService<ApiKey, ApiKey, ApiKey, any, any>> | undefined;
3
+ export default _default;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const common_1 = require("@appweaver/common");
4
+ const factory_1 = require("../../../factory");
5
+ const helper_1 = require("../../helper");
6
+ const context_1 = require("../../../context");
7
+ exports.default = common_1.config.SECURITY_API_KEY_ENABLED
8
+ ? (0, factory_1.createService)({
9
+ modelName: 'ApiKey',
10
+ beforeCreate: (data) => {
11
+ data.key = (0, common_1.randomString)(64, { special: false });
12
+ data.keyHash = (0, common_1.makeHash)(data.key);
13
+ // Add relation to the current user when creating a new API Key
14
+ data[(0, common_1.uncapitalize)((0, helper_1.resourceAuthModel)().name)] = {
15
+ id: (0, helper_1.currentAuthUser)().id
16
+ };
17
+ // Enforces max API key duration based on config value
18
+ const maxDuration = common_1.config.SECURITY_API_KEY_MAX_DURATION;
19
+ if (maxDuration) {
20
+ const maxExpiryDate = new Date(Date.now() + maxDuration * 1000);
21
+ if (!data.expiresAt ||
22
+ new Date(data.expiresAt).getTime() > maxExpiryDate.getTime()) {
23
+ data.expiresAt = maxExpiryDate;
24
+ }
25
+ }
26
+ },
27
+ afterCreate: async (data) => {
28
+ const service = (0, context_1.injectService)('ApiKey');
29
+ await service.update(data.id, { key: `...${data.key.slice(-6)}` });
30
+ data.key = `${data.id}${common_1.config.SECURITY_API_KEY_DELIMITER}${data.key}`;
31
+ }
32
+ })
33
+ : undefined;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@appweaver/common").ResourceModel | undefined;
2
+ export default _default;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const common_1 = require("@appweaver/common");
4
+ const factory_1 = require("../../../factory");
5
+ const shouldCreateModel = common_1.config.SECURITY_STORE_PROVIDER ===
6
+ '@appweaver/core/security/store/database-security-store' ||
7
+ common_1.config.SECURITY_STORE_KEEP_DATABASE_TABLE;
8
+ exports.default = shouldCreateModel
9
+ ? (0, factory_1.createModel)({
10
+ name: 'OneTimeToken',
11
+ audit: {
12
+ createdById: false
13
+ },
14
+ scalars: {
15
+ tokenHash: {
16
+ type: 'string',
17
+ maxLength: 511
18
+ },
19
+ purpose: {
20
+ type: 'string',
21
+ maxLength: 255
22
+ },
23
+ expiresAt: {
24
+ type: 'dateTime'
25
+ },
26
+ data: {
27
+ type: 'json'
28
+ }
29
+ },
30
+ index: [['tokenHash', 'purpose']]
31
+ })
32
+ : undefined;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@appweaver/common").ResourceModel;
2
+ export default _default;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const factory_1 = require("../../../factory");
4
+ exports.default = (0, factory_1.createModel)({
5
+ name: 'Permission',
6
+ scalars: {
7
+ name: {
8
+ type: 'string',
9
+ unique: true,
10
+ maxLength: 255
11
+ }
12
+ },
13
+ read: {
14
+ omit: ['updatedAt', 'createdAt', 'createdById']
15
+ }
16
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@appweaver/common").ResourceModel;
2
+ export default _default;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const factory_1 = require("../../../factory");
4
+ exports.default = (0, factory_1.createModel)({
5
+ name: 'Role',
6
+ scalars: {
7
+ name: {
8
+ type: 'string',
9
+ unique: true,
10
+ maxLength: 255
11
+ }
12
+ },
13
+ relations: {
14
+ permissions: {
15
+ model: 'Permission',
16
+ array: true
17
+ }
18
+ },
19
+ read: {
20
+ omit: ['updatedAt', 'createdAt', 'createdById']
21
+ }
22
+ });
@@ -0,0 +1,5 @@
1
+ import { SecurityStore, ValidationResult } from '@appweaver/common';
2
+ export declare class DatabaseSecurityStore extends SecurityStore {
3
+ generateOneTimeToken<T = any>(purpose: string, data: T, ttl: number): Promise<string>;
4
+ useOneTimeToken<T = any>(token: string, purpose: string, validateContent?: (value: T) => ValidationResult): Promise<T>;
5
+ }