@appconda/nextjs 1.0.161 → 1.1.2

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 (256) hide show
  1. package/dist/actions/actionClient.d.ts +8 -2
  2. package/dist/actions/actionClient.js +21 -15
  3. package/dist/actions/auth.d.ts +1 -0
  4. package/dist/actions/auth.js +7 -0
  5. package/dist/actions/authOptions.d.ts +5 -0
  6. package/dist/actions/authOptions.js +235 -0
  7. package/dist/actions/index.d.ts +3 -0
  8. package/dist/actions/index.js +4 -0
  9. package/dist/actions/nextAuthHandler.d.ts +1 -0
  10. package/dist/actions/nextAuthHandler.js +6 -0
  11. package/dist/client.d.ts +1 -1
  12. package/dist/client.js +1 -0
  13. package/dist/decorators/Cache.js +1 -0
  14. package/dist/decorators/CacheKey.js +1 -0
  15. package/dist/decorators/Invalidate.js +1 -0
  16. package/dist/enums/api-service.js +1 -0
  17. package/dist/enums/api.js +1 -0
  18. package/dist/enums/auth-method.js +1 -0
  19. package/dist/enums/browser.js +1 -0
  20. package/dist/enums/compression.js +1 -0
  21. package/dist/enums/credit-card.js +1 -0
  22. package/dist/enums/database-usage-range.js +1 -0
  23. package/dist/enums/email-template-locale.js +1 -0
  24. package/dist/enums/email-template-type.js +1 -0
  25. package/dist/enums/entities/EntityLimitType.js +1 -0
  26. package/dist/enums/entities/PropertyAttributeName.js +1 -0
  27. package/dist/enums/entities/PropertyCondition.js +1 -0
  28. package/dist/enums/entities/PropertyType.js +1 -0
  29. package/dist/enums/entities/PropertyValueType.js +1 -0
  30. package/dist/enums/entities/RowAccess.js +1 -0
  31. package/dist/enums/entities/ViewFilterCondition.js +1 -0
  32. package/dist/enums/execution-method.js +1 -0
  33. package/dist/enums/flag.js +1 -0
  34. package/dist/enums/function-usage-range.js +1 -0
  35. package/dist/enums/image-format.js +1 -0
  36. package/dist/enums/image-gravity.js +1 -0
  37. package/dist/enums/index-type.js +1 -0
  38. package/dist/enums/messaging-provider-type.js +1 -0
  39. package/dist/enums/name.js +1 -0
  40. package/dist/enums/o-auth-provider copy.js +1 -0
  41. package/dist/enums/password-hash.js +1 -0
  42. package/dist/enums/platform-type.js +1 -0
  43. package/dist/enums/project-usage-range.js +1 -0
  44. package/dist/enums/region.js +1 -0
  45. package/dist/enums/relation-mutate.js +1 -0
  46. package/dist/enums/relationship-type.js +1 -0
  47. package/dist/enums/resource-type.js +1 -0
  48. package/dist/enums/runtime.js +1 -0
  49. package/dist/enums/s-m-t-p-secure.js +1 -0
  50. package/dist/enums/shared/ApplicationLayout.js +1 -0
  51. package/dist/enums/shared/Colors.js +1 -0
  52. package/dist/enums/shared/InputType.js +1 -0
  53. package/dist/enums/shared/Periodicity.js +1 -0
  54. package/dist/enums/shared/SvgIcon.js +1 -0
  55. package/dist/enums/shared/Theme.js +1 -0
  56. package/dist/enums/sms-template-locale.js +1 -0
  57. package/dist/enums/sms-template-type.js +1 -0
  58. package/dist/enums/smtp-encryption.js +1 -0
  59. package/dist/enums/storage-usage-range.js +1 -0
  60. package/dist/enums/subscriptions/PricingModel.js +1 -0
  61. package/dist/enums/subscriptions/SubscriptionBillingPeriod.js +1 -0
  62. package/dist/enums/subscriptions/SubscriptionFeatureLimitType.js +1 -0
  63. package/dist/enums/subscriptions/SubscriptionPriceType.js +1 -0
  64. package/dist/enums/tenants/LinkedAccountStatus.js +1 -0
  65. package/dist/enums/tenants/TenantUserJoined.js +1 -0
  66. package/dist/enums/tenants/TenantUserStatus.js +1 -0
  67. package/dist/enums/tenants/TenantUserType.js +1 -0
  68. package/dist/enums/user-usage-range.js +1 -0
  69. package/dist/getAppcondaClient.js +5 -3
  70. package/dist/getSDKForCurrentUser.d.ts +8 -2
  71. package/dist/getSDKForCurrentUser.js +13 -5
  72. package/dist/getSDKForService.js +3 -1
  73. package/dist/getSDKForTenant.d.ts +20 -0
  74. package/dist/getSDKForTenant.js +44 -0
  75. package/dist/id.js +1 -0
  76. package/dist/index.d.ts +4 -1
  77. package/dist/index.js +5 -1
  78. package/dist/inputFile.js +1 -0
  79. package/dist/lib/Cache/Adapter.js +1 -0
  80. package/dist/lib/Cache/Adapters/Filesystem.js +1 -0
  81. package/dist/lib/Cache/Adapters/Memory.js +1 -0
  82. package/dist/lib/Cache/Adapters/None.js +1 -0
  83. package/dist/lib/Cache/Adapters/Sharding.js +1 -0
  84. package/dist/lib/Cache/Cache.js +1 -0
  85. package/dist/lib/Cache/index.js +1 -0
  86. package/dist/lib/Cache/test.js +1 -0
  87. package/dist/lib/Registry/Registry.js +1 -0
  88. package/dist/lib/Registry/index.js +1 -0
  89. package/dist/lib/Services.js +1 -0
  90. package/dist/lib/crypto.d.ts +23 -0
  91. package/dist/lib/crypto.js +78 -0
  92. package/dist/lib/env.d.ts +1 -0
  93. package/dist/lib/env.js +137 -0
  94. package/dist/lib/errors.d.ts +70 -0
  95. package/dist/lib/errors.js +76 -0
  96. package/dist/lib/index.d.ts +2 -0
  97. package/dist/lib/index.js +3 -0
  98. package/dist/lib/jwt.d.ts +12 -0
  99. package/dist/lib/jwt.js +103 -0
  100. package/dist/models.js +1 -0
  101. package/dist/modules/account/actions.d.ts +20 -14
  102. package/dist/modules/account/actions.js +1 -0
  103. package/dist/modules/account/enums/authentication-factor.js +1 -0
  104. package/dist/modules/account/enums/authenticator-type.js +1 -0
  105. package/dist/modules/account/enums/o-auth-provider.js +1 -0
  106. package/dist/modules/account/index.js +1 -0
  107. package/dist/modules/account/schema.d.ts +8 -8
  108. package/dist/modules/account/schema.js +1 -0
  109. package/dist/modules/account/service.js +1 -0
  110. package/dist/modules/account/types.js +1 -0
  111. package/dist/modules/acl/service.d.ts +26 -0
  112. package/dist/modules/acl/service.js +27 -0
  113. package/dist/modules/agent/action.d.ts +27 -23
  114. package/dist/modules/agent/action.js +1 -0
  115. package/dist/modules/agent/index.js +1 -0
  116. package/dist/modules/agent/schema.d.ts +18 -18
  117. package/dist/modules/agent/schema.js +1 -0
  118. package/dist/modules/agent/service.js +1 -0
  119. package/dist/modules/agent/types.js +1 -0
  120. package/dist/modules/ai/index.js +1 -0
  121. package/dist/modules/ai/node/actions.d.ts +1 -1
  122. package/dist/modules/ai/node/actions.js +1 -0
  123. package/dist/modules/ai/node/index.js +1 -0
  124. package/dist/modules/ai/node/service.js +1 -0
  125. package/dist/modules/index.d.ts +3 -0
  126. package/dist/modules/index.js +4 -0
  127. package/dist/modules/scheduled-job/action.d.ts +97 -0
  128. package/dist/modules/scheduled-job/action.js +77 -0
  129. package/dist/modules/scheduled-job/index.d.ts +7 -0
  130. package/dist/modules/scheduled-job/index.js +8 -0
  131. package/dist/modules/scheduled-job/lib/Schedules.d.ts +32 -0
  132. package/dist/modules/scheduled-job/lib/Schedules.js +64 -0
  133. package/dist/modules/scheduled-job/lib/handler.d.ts +12 -0
  134. package/dist/modules/scheduled-job/lib/handler.js +23 -0
  135. package/dist/modules/scheduled-job/lib/jobs/index.d.ts +2 -0
  136. package/dist/modules/scheduled-job/lib/jobs/index.js +3 -0
  137. package/dist/modules/scheduled-job/lib/jobs/job1.d.ts +1 -0
  138. package/dist/modules/scheduled-job/lib/jobs/job1.js +30 -0
  139. package/dist/modules/scheduled-job/lib/jobs/log-job.d.ts +1 -0
  140. package/dist/modules/scheduled-job/lib/jobs/log-job.js +9 -0
  141. package/dist/modules/scheduled-job/lib/wait.d.ts +8 -0
  142. package/dist/modules/scheduled-job/lib/wait.js +13 -0
  143. package/dist/modules/scheduled-job/schema.d.ts +52 -0
  144. package/dist/modules/scheduled-job/schema.js +23 -0
  145. package/dist/modules/scheduled-job/service.d.ts +13 -0
  146. package/dist/modules/scheduled-job/service.js +25 -0
  147. package/dist/modules/scheduled-job/types.d.ts +29 -0
  148. package/dist/modules/scheduled-job/types.js +2 -0
  149. package/dist/modules/task/action.d.ts +201 -0
  150. package/dist/modules/task/action.js +147 -0
  151. package/dist/modules/task/index.d.ts +4 -0
  152. package/dist/modules/task/index.js +5 -0
  153. package/dist/modules/task/schema.d.ts +107 -0
  154. package/dist/modules/task/schema.js +44 -0
  155. package/dist/modules/task/service.d.ts +19 -0
  156. package/dist/modules/task/service.js +43 -0
  157. package/dist/modules/task/types.d.ts +84 -0
  158. package/dist/modules/task/types.js +2 -0
  159. package/dist/modules/tenant/actions.d.ts +49 -0
  160. package/dist/modules/tenant/actions.js +38 -0
  161. package/dist/modules/tenant/index.d.ts +3 -0
  162. package/dist/modules/tenant/index.js +4 -0
  163. package/dist/{services → modules/tenant}/tenant.d.ts +3 -3
  164. package/dist/modules/tenant/tenant.js +125 -0
  165. package/dist/modules/tenant/types.d.ts +11 -0
  166. package/dist/modules/tenant/types.js +2 -0
  167. package/dist/modules/waitlist/action.d.ts +31 -29
  168. package/dist/modules/waitlist/action.js +1 -0
  169. package/dist/modules/waitlist/index.js +1 -0
  170. package/dist/modules/waitlist/schema.d.ts +12 -12
  171. package/dist/modules/waitlist/schema.js +1 -0
  172. package/dist/modules/waitlist/service.js +1 -0
  173. package/dist/modules/waitlist/types.js +1 -0
  174. package/dist/permission.js +1 -0
  175. package/dist/query.js +1 -0
  176. package/dist/role.js +1 -0
  177. package/dist/schemas/nodes.js +1 -0
  178. package/dist/service-client.js +1 -0
  179. package/dist/service.js +1 -0
  180. package/dist/services/applets.js +1 -0
  181. package/dist/services/avatars.js +1 -0
  182. package/dist/services/chat-flow.js +1 -0
  183. package/dist/services/community.js +1 -0
  184. package/dist/services/configuration.js +1 -0
  185. package/dist/services/databases.js +1 -0
  186. package/dist/services/functions.js +1 -0
  187. package/dist/services/graphql.js +1 -0
  188. package/dist/services/health.js +1 -0
  189. package/dist/services/locale.js +1 -0
  190. package/dist/services/messaging.js +1 -0
  191. package/dist/services/permissions.js +1 -0
  192. package/dist/services/pricing.js +1 -0
  193. package/dist/services/projects.js +1 -0
  194. package/dist/services/roles.js +1 -0
  195. package/dist/services/schema.js +1 -0
  196. package/dist/services/storage.js +1 -0
  197. package/dist/services/subscription.js +1 -0
  198. package/dist/services/teams.js +1 -0
  199. package/dist/services/tenant-subscription.js +1 -0
  200. package/dist/services/users.js +1 -0
  201. package/package.json +4 -1
  202. package/src/actions/actionClient.ts +13 -6
  203. package/src/actions/auth.ts +7 -0
  204. package/src/actions/authOptions.ts +255 -0
  205. package/src/actions/index.ts +3 -0
  206. package/src/actions/nextAuthHandler.ts +9 -0
  207. package/src/client.ts +1 -1
  208. package/src/getAppcondaClient.ts +4 -3
  209. package/src/getSDKForCurrentUser.ts +12 -5
  210. package/src/getSDKForService.ts +2 -1
  211. package/src/getSDKForTenant.ts +52 -0
  212. package/src/index.ts +4 -2
  213. package/src/lib/crypto.ts +105 -0
  214. package/src/lib/env.ts +145 -0
  215. package/src/lib/errors.ts +138 -0
  216. package/src/lib/index.ts +2 -0
  217. package/src/lib/jwt.ts +113 -0
  218. package/src/modules/account/actions.ts +1 -1
  219. package/src/modules/acl/service.ts +55 -0
  220. package/src/modules/agent/action.ts +2 -0
  221. package/src/modules/ai/node/actions.ts +0 -1
  222. package/src/modules/index.ts +4 -1
  223. package/src/modules/scheduled-job/action.ts +94 -0
  224. package/src/modules/scheduled-job/index.ts +8 -0
  225. package/src/modules/scheduled-job/lib/Schedules.ts +103 -0
  226. package/src/modules/scheduled-job/lib/handler.ts +27 -0
  227. package/src/modules/scheduled-job/lib/jobs/index.ts +2 -0
  228. package/src/modules/scheduled-job/lib/jobs/job1.ts +34 -0
  229. package/src/modules/scheduled-job/lib/jobs/log-job.ts +9 -0
  230. package/src/modules/scheduled-job/lib/wait.ts +17 -0
  231. package/src/modules/scheduled-job/schema.ts +31 -0
  232. package/src/modules/scheduled-job/service.ts +37 -0
  233. package/src/modules/scheduled-job/types.ts +35 -0
  234. package/src/modules/task/action.ts +175 -0
  235. package/src/modules/task/index.ts +4 -0
  236. package/src/modules/task/schema.ts +53 -0
  237. package/src/modules/task/service.ts +62 -0
  238. package/src/modules/task/types.ts +89 -0
  239. package/src/modules/tenant/actions.ts +46 -0
  240. package/src/modules/tenant/index.ts +3 -0
  241. package/src/{services → modules/tenant}/tenant.ts +3 -4
  242. package/src/modules/tenant/types.ts +12 -0
  243. package/tsconfig.json +4 -1
  244. package/dist/actions/nodes.d.ts +0 -4
  245. package/dist/actions/nodes.js +0 -15
  246. package/dist/enums/authentication-factor.d.ts +0 -6
  247. package/dist/enums/authentication-factor.js +0 -7
  248. package/dist/enums/authenticator-type.d.ts +0 -3
  249. package/dist/enums/authenticator-type.js +0 -4
  250. package/dist/enums/o-auth-provider.d.ts +0 -41
  251. package/dist/enums/o-auth-provider.js +0 -42
  252. package/dist/services/account.d.ts +0 -530
  253. package/dist/services/account.js +0 -1259
  254. package/dist/services/node.d.ts +0 -5
  255. package/dist/services/node.js +0 -11
  256. package/dist/services/tenant.js +0 -124
package/src/client.ts CHANGED
@@ -291,7 +291,7 @@ class Client {
291
291
  }
292
292
 
293
293
  let start = 0;
294
- let response = null;
294
+ let response: any = null;
295
295
 
296
296
  while (start < file.size) {
297
297
  let end = start + Client.CHUNK_SIZE; // Prepare end for the next chunk
@@ -1,4 +1,5 @@
1
1
  import { Client } from "./client";
2
+ import { getEnv } from "./lib/env";
2
3
 
3
4
  function getPortAndHostname(urlString: string): { hostname: string; port: string; protocol: string } {
4
5
  try {
@@ -17,8 +18,8 @@ function getPortAndHostname(urlString: string): { hostname: string; port: string
17
18
  export async function getAppcondaClient() {
18
19
 
19
20
  let url;
20
- if (process.env.NEXT_PUBLIC_APPCONDA_CLIENT_ENDPOINT) {
21
- url = process.env.NEXT_PUBLIC_APPCONDA_CLIENT_ENDPOINT;
21
+ if (getEnv().APPCONDA_ENDPOINT) {
22
+ url = getEnv().APPCONDA_ENDPOINT;
22
23
  } else if (typeof window !== 'undefined') {
23
24
  const hostInfo = getPortAndHostname(window.location.href);
24
25
  if (hostInfo.port) {
@@ -27,7 +28,7 @@ export async function getAppcondaClient() {
27
28
  url = `${hostInfo.protocol}//${hostInfo.hostname}/v1`
28
29
  }
29
30
  } else {
30
- url = 'http://appconda/v1'
31
+ url = getEnv().APPCONDA_ENDPOINT || 'http://appconda/v1'
31
32
  }
32
33
 
33
34
  /* if (ApplicationConfig.Port == null) {
@@ -9,7 +9,6 @@ import { Roles } from "./services/roles";
9
9
  import { Schemas } from "./services/schema";
10
10
  import { Subscription } from "./services/subscription";
11
11
  import { Teams } from "./services/teams";
12
- import { Tenant } from "./services/tenant";
13
12
  import { TenantSubscription } from "./services/tenant-subscription";
14
13
  import { Users } from "./services/users";
15
14
  import { Permissions } from "./services/permissions";
@@ -18,6 +17,10 @@ import { Account } from "./modules/account/service";
18
17
  import { Node } from "./modules/ai/node/service";
19
18
  import { AgentService } from "./modules/agent/service";
20
19
  import { ChatFlow } from "./services/chat-flow";
20
+ import { TenantService } from "./modules";
21
+ import { Acl } from "./modules/acl/service";
22
+ import { TaskService } from "./modules/task/service";
23
+ import { ScheduledJobService } from "./modules/scheduled-job";
21
24
 
22
25
  export async function getSDKForCurrentUser() {
23
26
  const adminClient = await getAppcondaClient();
@@ -40,7 +43,7 @@ export async function getSDKForCurrentUser() {
40
43
  const users = new Users(adminClient);
41
44
  const teams = new Teams(adminClient);
42
45
 
43
- const tenants = new Tenant(adminClient);
46
+ const tenants = new TenantService(adminClient);
44
47
  const roles = new Roles(adminClient);
45
48
  const permissions = new Permissions(adminClient);
46
49
  const schemas = new Schemas(adminClient);
@@ -52,12 +55,14 @@ export async function getSDKForCurrentUser() {
52
55
  const subscription = new Subscription(adminClient);
53
56
  const pricing = new Pricing(adminClient);
54
57
  const configuration = new Configuration(adminClient);
55
- //const acl = new Acl(adminClient);
58
+ const acl = new Acl(adminClient);
56
59
 
57
60
  const node = new Node(adminClient);
58
61
  const waitlist = new WaitlistService(adminClient);
59
62
  const agent = new AgentService(adminClient);
60
63
  const chatFlow = new ChatFlow(adminClient);
64
+ const task = new TaskService(adminClient);
65
+ const scheduledJob = new ScheduledJobService(adminClient);
61
66
 
62
67
  return {
63
68
  currentUser,
@@ -75,10 +80,12 @@ export async function getSDKForCurrentUser() {
75
80
  subscription,
76
81
  pricing,
77
82
  configuration,
78
- // acl,
83
+ acl,
79
84
  node,
80
85
  waitlist,
81
86
  agent,
82
- chatFlow
87
+ chatFlow,
88
+ task,
89
+ scheduledJob
83
90
  }
84
91
  }
@@ -1,11 +1,12 @@
1
1
  import { getAppcondaClient } from "./getAppcondaClient";
2
+ import { getEnv } from "./lib/env";
2
3
  import { WaitlistService } from "./modules";
3
4
  import { Configuration } from "./services/configuration";
4
5
 
5
6
  export async function getSDKForService() {
6
7
  const adminClient = await getAppcondaClient();
7
8
 
8
- adminClient.addHeader('x-service-token', process.env._SERVICE_TOKEN ?? '');
9
+ adminClient.addHeader('x-service-token', getEnv()._SERVICE_TOKEN ?? '');
9
10
  /*
10
11
  const accounts = new Account(adminClient);
11
12
  const databases = new Databases(adminClient);
@@ -0,0 +1,52 @@
1
+ import { cookies } from "next/headers";
2
+ import { getAppcondaClient } from "./getAppcondaClient";
3
+ import { Account, TenantService } from "./modules";
4
+ import { Databases } from "./services/databases";
5
+ import { Projects } from "./services/projects";
6
+ import { Roles } from "./services/roles";
7
+ import { Schemas } from "./services/schema";
8
+ import { Teams } from "./services/teams";
9
+ import { Users } from "./services/users";
10
+ import { Permissions } from "./services/permissions";
11
+
12
+ export async function getSDKForTenant(tenantId: string) {
13
+ const adminClient = await getAppcondaClient();
14
+ adminClient.setProject(tenantId);
15
+ adminClient.setMode('admin');
16
+
17
+ const c = await cookies()
18
+ const s = c.get('a_session') || c.get('a_session_console_legacy');
19
+ if (!s || !s.value) {
20
+ throw new Error("No session");
21
+ }
22
+
23
+ adminClient.setSession(s.value);
24
+
25
+ const accounts = new Account(adminClient);
26
+ const databases = new Databases(adminClient);
27
+
28
+ const projects = new Projects(adminClient);
29
+
30
+ const currentUser = await accounts.get();
31
+
32
+ const users = new Users(adminClient);
33
+ const teams = new Teams(adminClient);
34
+
35
+ const tenants = new TenantService(adminClient);
36
+ const roles = new Roles(adminClient);
37
+ const permissions = new Permissions(adminClient);
38
+ const schemas = new Schemas(adminClient);
39
+
40
+ return {
41
+ currentUser,
42
+ accounts,
43
+ databases,
44
+ projects,
45
+ users,
46
+ teams,
47
+ tenants,
48
+ roles,
49
+ permissions,
50
+ schemas
51
+ }
52
+ }
package/src/index.ts CHANGED
@@ -36,7 +36,9 @@ export { PasswordHash } from './enums/password-hash';
36
36
  export { MessagingProviderType } from './enums/messaging-provider-type';
37
37
  export { getSDKForCurrentUser } from './getSDKForCurrentUser';
38
38
  export { getSDKForService } from './getSDKForService';
39
+ export { getAppcondaClient } from './getAppcondaClient';
40
+ export { getSDKForTenant } from './getSDKForTenant';
39
41
  export * from './modules';
40
42
  export type { SafeActionFn } from 'next-safe-action';
41
-
42
- export { getAppcondaClient } from './getAppcondaClient';
43
+ export * from './actions';
44
+ export * from './lib';
@@ -0,0 +1,105 @@
1
+ import crypto from "crypto";
2
+ import { createCipheriv, createDecipheriv, createHash, createHmac, randomBytes } from "crypto";
3
+ import { getEnv } from "./env";
4
+
5
+
6
+ const ALGORITHM = "aes256";
7
+ const INPUT_ENCODING = "utf8";
8
+ const OUTPUT_ENCODING = "hex";
9
+
10
+ const IV_LENGTH = 16; // AES blocksize
11
+
12
+ /**
13
+ *
14
+ * @param text Value to be encrypted
15
+ * @param key Key used to encrypt value must be 32 bytes for AES256 encryption algorithm
16
+ *
17
+ * @returns Encrypted value using key
18
+ */
19
+ export const symmetricEncrypt = (text: string, key: string) => {
20
+ const BUFFER_ENCODING = getEnv().ENCRYPTION_KEY!.length === 32 ? "latin1" : "hex";
21
+ const _key = Buffer.from(key, BUFFER_ENCODING);
22
+ const iv = crypto.randomBytes(IV_LENGTH);
23
+
24
+ // @ts-ignore -- the package needs to be built
25
+ const cipher = crypto.createCipheriv(ALGORITHM, _key, iv);
26
+ let ciphered = cipher.update(text, INPUT_ENCODING, OUTPUT_ENCODING);
27
+ ciphered += cipher.final(OUTPUT_ENCODING);
28
+ const ciphertext = iv.toString(OUTPUT_ENCODING) + ":" + ciphered;
29
+
30
+ return ciphertext;
31
+ };
32
+
33
+ /**
34
+ *
35
+ * @param text Value to decrypt
36
+ * @param key Key used to decrypt value must be 32 bytes for AES256 encryption algorithm
37
+ */
38
+ export const symmetricDecrypt = (text: string, key: string) => {
39
+ const BUFFER_ENCODING = getEnv().ENCRYPTION_KEY!.length === 32 ? "latin1" : "hex";
40
+ const _key = Buffer.from(key, BUFFER_ENCODING);
41
+
42
+ const components = text.split(":");
43
+ const iv_from_ciphertext = Buffer.from(components.shift() || "", OUTPUT_ENCODING);
44
+ // @ts-ignore -- the package needs to be built
45
+ const decipher = crypto.createDecipheriv(ALGORITHM, _key, iv_from_ciphertext);
46
+ let deciphered = decipher.update(components.join(":"), OUTPUT_ENCODING, INPUT_ENCODING);
47
+ deciphered += decipher.final(INPUT_ENCODING);
48
+
49
+ return deciphered;
50
+ };
51
+
52
+ export const getHash = (key: string): string => createHash("sha256").update(key).digest("hex");
53
+
54
+ // create an aes128 encryption function
55
+ export const encryptAES128 = (encryptionKey: string, data: string): string => {
56
+ // @ts-ignore -- the package needs to be built
57
+ const cipher = createCipheriv("aes-128-ecb", Buffer.from(encryptionKey, "base64"), "");
58
+ let encrypted = cipher.update(data, "utf-8", "hex");
59
+ encrypted += cipher.final("hex");
60
+ return encrypted;
61
+ };
62
+ // create an aes128 decryption function
63
+ export const decryptAES128 = (encryptionKey: string, data: string): string => {
64
+ // @ts-ignore -- the package needs to be built
65
+ const cipher = createDecipheriv("aes-128-ecb", Buffer.from(encryptionKey, "base64"), "");
66
+ let decrypted = cipher.update(data, "hex", "utf-8");
67
+ decrypted += cipher.final("utf-8");
68
+ return decrypted;
69
+ };
70
+
71
+ export const generateLocalSignedUrl = (
72
+ fileName: string,
73
+ environmentId: string,
74
+ fileType: string
75
+ ): { signature: string; uuid: string; timestamp: number } => {
76
+ const uuid = randomBytes(16).toString("hex");
77
+ const timestamp = Date.now();
78
+ const data = `${uuid}:${fileName}:${environmentId}:${fileType}:${timestamp}`;
79
+ const signature = createHmac("sha256", getEnv().ENCRYPTION_KEY!).update(data).digest("hex");
80
+ return { signature, uuid, timestamp };
81
+ };
82
+
83
+ export const validateLocalSignedUrl = (
84
+ uuid: string,
85
+ fileName: string,
86
+ environmentId: string,
87
+ fileType: string,
88
+ timestamp: number,
89
+ signature: string,
90
+ secret: string
91
+ ): boolean => {
92
+ const data = `${uuid}:${fileName}:${environmentId}:${fileType}:${timestamp}`;
93
+ const expectedSignature = createHmac("sha256", secret).update(data).digest("hex");
94
+
95
+ if (expectedSignature !== signature) {
96
+ return false;
97
+ }
98
+
99
+ // valid for 5 minutes
100
+ if (Date.now() - timestamp > 1000 * 60 * 5) {
101
+ return false;
102
+ }
103
+
104
+ return true;
105
+ };
package/src/lib/env.ts ADDED
@@ -0,0 +1,145 @@
1
+ import { createEnv } from "@t3-oss/env-nextjs";
2
+ import { z } from "zod";
3
+
4
+
5
+ export const getEnv = (() => {
6
+ let env: any = null;
7
+ return () => {
8
+ if (env == null) {
9
+ env = createEnv({
10
+ /*
11
+ * Serverside Environment variables, not available on the client.
12
+ * Will throw if you access these variables on the client.
13
+ */
14
+ server: {
15
+ APPCONDA_ENDPOINT: z.string(),
16
+ APPCONDA_CLIENT_ENDPOINT: z.string(),
17
+ _SERVICE_TOKEN: z.string(),
18
+ ENTERPRISE_LICENSE_KEY: z.string(),
19
+ NEXTAUTH_SECRET: z.string().min(1),
20
+ ENCRYPTION_KEY: z.string().length(64).or(z.string().length(32)),
21
+ CRON_SECRET: z.string().min(10),
22
+ _ADMIN_DOMAIN: z.string().optional(),
23
+ /* AI_AZURE_LLM_API_KEY: z.string().optional(),
24
+ AI_AZURE_EMBEDDINGS_DEPLOYMENT_ID: z.string().optional(),
25
+ AI_AZURE_LLM_DEPLOYMENT_ID: z.string().optional(),
26
+ AI_AZURE_EMBEDDINGS_RESSOURCE_NAME: z.string().optional(),
27
+ AI_AZURE_LLM_RESSOURCE_NAME: z.string().optional(),
28
+ AIRTABLE_CLIENT_ID: z.string().optional(),
29
+ AZUREAD_CLIENT_ID: z.string().optional(),
30
+ AZUREAD_CLIENT_SECRET: z.string().optional(),
31
+ AZUREAD_TENANT_ID: z.string().optional(),
32
+ CRON_SECRET: z.string().min(10),
33
+ CUSTOMER_IO_API_KEY: z.string().optional(),
34
+ CUSTOMER_IO_SITE_ID: z.string().optional(),
35
+ DATABASE_URL: z.string().url(),
36
+ DEBUG: z.enum(["1", "0"]).optional(),
37
+ DEFAULT_ORGANIZATION_ID: z.string().optional(),
38
+ DEFAULT_ORGANIZATION_ROLE: z.enum(["owner", "manager", "member", "billing"]).optional(),
39
+ E2E_TESTING: z.enum(["1", "0"]).optional(),
40
+ EMAIL_AUTH_DISABLED: z.enum(["1", "0"]).optional(),
41
+ EMAIL_VERIFICATION_DISABLED: z.enum(["1", "0"]).optional(),
42
+
43
+ ENTERPRISE_LICENSE_KEY: z.string().optional(),
44
+ FORMBRICKS_ENCRYPTION_KEY: z.string().length(24).or(z.string().length(0)).optional(),
45
+ GITHUB_ID: z.string().optional(),
46
+ GITHUB_SECRET: z.string().optional(),
47
+ GOOGLE_CLIENT_ID: z.string().optional(),
48
+ GOOGLE_CLIENT_SECRET: z.string().optional(),
49
+ GOOGLE_SHEETS_CLIENT_ID: z.string().optional(),
50
+ GOOGLE_SHEETS_CLIENT_SECRET: z.string().optional(),
51
+ GOOGLE_SHEETS_REDIRECT_URL: z.string().optional(),
52
+ HTTP_PROXY: z.string().url().optional(),
53
+ HTTPS_PROXY: z.string().url().optional(),
54
+ IMPRINT_URL: z
55
+ .string()
56
+ .url()
57
+ .optional()
58
+ .or(z.string().refine((str) => str === "")),
59
+ IMPRINT_ADDRESS: z.string().optional(),
60
+ INVITE_DISABLED: z.enum(["1", "0"]).optional(),
61
+ INTERCOM_SECRET_KEY: z.string().optional(),
62
+ IS_FORMBRICKS_CLOUD: z.enum(["1", "0"]).optional(),
63
+ MAIL_FROM: z.string().email().optional(),
64
+
65
+ NOTION_OAUTH_CLIENT_ID: z.string().optional(),
66
+ NOTION_OAUTH_CLIENT_SECRET: z.string().optional(),
67
+ OIDC_CLIENT_ID: z.string().optional(),
68
+ OIDC_CLIENT_SECRET: z.string().optional(),
69
+ OIDC_DISPLAY_NAME: z.string().optional(),
70
+ OIDC_ISSUER: z.string().optional(),
71
+ OIDC_SIGNING_ALGORITHM: z.string().optional(),
72
+ OPENTELEMETRY_LISTENER_URL: z.string().optional(),
73
+ REDIS_URL: z.string().optional(),
74
+ REDIS_HTTP_URL: z.string().optional(),
75
+ PASSWORD_RESET_DISABLED: z.enum(["1", "0"]).optional(),
76
+ PRIVACY_URL: z
77
+ .string()
78
+ .url()
79
+ .optional()
80
+ .or(z.string().refine((str) => str === "")),
81
+ RATE_LIMITING_DISABLED: z.enum(["1", "0"]).optional(),
82
+ S3_ACCESS_KEY: z.string().optional(),
83
+ S3_BUCKET_NAME: z.string().optional(),
84
+ S3_REGION: z.string().optional(),
85
+ S3_SECRET_KEY: z.string().optional(),
86
+ S3_ENDPOINT_URL: z.string().optional(),
87
+ S3_FORCE_PATH_STYLE: z.enum(["1", "0"]).optional(),
88
+ SHORT_URL_BASE: z.string().url().optional().or(z.string().length(0)),
89
+ SIGNUP_DISABLED: z.enum(["1", "0"]).optional(),
90
+ SLACK_CLIENT_ID: z.string().optional(),
91
+ SLACK_CLIENT_SECRET: z.string().optional(),
92
+ SMTP_HOST: z.string().min(1).optional(),
93
+ SMTP_PORT: z.string().min(1).optional(),
94
+ SMTP_SECURE_ENABLED: z.enum(["1", "0"]).optional(),
95
+ SMTP_USER: z.string().min(1).optional(),
96
+ SMTP_PASSWORD: z.string().min(1).optional(),
97
+ SMTP_AUTHENTICATED: z.enum(["1", "0"]).optional(),
98
+ SMTP_REJECT_UNAUTHORIZED_TLS: z.enum(["1", "0"]).optional(),
99
+ STRIPE_SECRET_KEY: z.string().optional(),
100
+ STRIPE_WEBHOOK_SECRET: z.string().optional(),
101
+ TELEMETRY_DISABLED: z.enum(["1", "0"]).optional(),
102
+ TERMS_URL: z
103
+ .string()
104
+ .url()
105
+ .optional()
106
+ .or(z.string().refine((str) => str === "")),
107
+ TURNSTILE_SECRET_KEY: z.string().optional(),
108
+ UPLOADS_DIR: z.string().min(1).optional(),
109
+ VERCEL_URL: z.string().optional(),
110
+
111
+ ADMIN_URL: z.string().url().optional(),
112
+ UNSPLASH_ACCESS_KEY: z.string().optional(),
113
+ LANGFUSE_SECRET_KEY: z.string().optional(),
114
+ LANGFUSE_PUBLIC_KEY: z.string().optional(),
115
+ LANGFUSE_BASEURL: z.string().optional(), */
116
+ },
117
+
118
+ /*
119
+ * Due to how Next.js bundles environment variables on Edge and Client,
120
+ * we need to manually destructure them to make sure all are included in bundle.
121
+ *
122
+ * 💡 You'll get type errors if not all variables from `server` & `client` are included here.
123
+ */
124
+ runtimeEnv: {
125
+ APPCONDA_ENDPOINT: process.env.APPCONDA_ENDPOINT,
126
+ APPCONDA_CLIENT_ENDPOINT: process.env.APPCONDA_CLIENT_ENDPOINT,
127
+ _SERVICE_TOKEN: process.env._SERVICE_TOKEN,
128
+ ENTERPRISE_LICENSE_KEY: process.env.ENTERPRISE_LICENSE_KEY,
129
+ NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
130
+ ENCRYPTION_KEY: process.env.ENCRYPTION_KEY,
131
+ CRON_SECRET: process.env.CRON_SECRET,
132
+ _ADMIN_DOMAIN: process.env._ADMIN_DOMAIN,
133
+ },
134
+ });
135
+ console.log(env);
136
+ }
137
+
138
+ return env;
139
+
140
+ };
141
+ })();
142
+
143
+
144
+
145
+
@@ -0,0 +1,138 @@
1
+ import { z } from "zod";
2
+
3
+ class ResourceNotFoundError extends Error {
4
+ statusCode = 404;
5
+ resourceId: string | null;
6
+ resourceType: string;
7
+
8
+ constructor(resource: string, id: string | null) {
9
+ super(id ? `${resource} with ID ${id} not found` : `${resource} not found`);
10
+ this.name = "ResourceNotFoundError";
11
+ this.resourceType = resource;
12
+ this.resourceId = id;
13
+ }
14
+ }
15
+
16
+ class InvalidInputError extends Error {
17
+ statusCode = 400;
18
+ constructor(message: string) {
19
+ super(message);
20
+ this.name = "InvalidInputError";
21
+ }
22
+ }
23
+
24
+ class ValidationError extends Error {
25
+ statusCode = 400;
26
+ constructor(message: string) {
27
+ super(message);
28
+ this.name = "ValidationError";
29
+ }
30
+ }
31
+
32
+ class UnknownError extends Error {
33
+ statusCode = 500;
34
+ constructor(message: string) {
35
+ super(message);
36
+ this.name = "UnknownError";
37
+ }
38
+ }
39
+
40
+ class DatabaseError extends Error {
41
+ statusCode = 500;
42
+ constructor(message: string) {
43
+ super(message);
44
+ this.name = "DatabaseError";
45
+ }
46
+ }
47
+
48
+ class UniqueConstraintError extends Error {
49
+ statusCode = 409;
50
+ constructor(message: string) {
51
+ super(message);
52
+ this.name = "UniqueConstraintError";
53
+ }
54
+ }
55
+
56
+ class ForeignKeyConstraintError extends Error {
57
+ statusCode = 409;
58
+ constructor(message: string) {
59
+ super(message);
60
+ this.name = "ForeignKeyConstraintError";
61
+ }
62
+ }
63
+
64
+ class OperationNotAllowedError extends Error {
65
+ statusCode = 403;
66
+ constructor(message: string) {
67
+ super(message);
68
+ this.name = "OperationNotAllowedError";
69
+ }
70
+ }
71
+
72
+ class AuthenticationError extends Error {
73
+ statusCode = 401;
74
+ constructor(message: string) {
75
+ super(message);
76
+ this.name = "AuthenticationError";
77
+ }
78
+ }
79
+
80
+ class AuthorizationError extends Error {
81
+ statusCode = 403;
82
+ constructor(message: string) {
83
+ super(message);
84
+ this.name = "AuthorizationError";
85
+ }
86
+ }
87
+
88
+ interface NetworkError {
89
+ code: "network_error";
90
+ message: string;
91
+ status: number;
92
+ url: URL;
93
+ responseMessage?: string;
94
+ details?: Record<string, string | string[] | number | number[] | boolean | boolean[]>;
95
+ }
96
+
97
+ interface ForbiddenError {
98
+ code: "forbidden";
99
+ message: string;
100
+ status: number;
101
+ url: URL;
102
+ responseMessage?: string;
103
+ details?: Record<string, string | string[] | number | number[] | boolean | boolean[]>;
104
+ }
105
+
106
+ export const ZErrorHandler = z.function().args(z.any()).returns(z.void());
107
+
108
+ export {
109
+ ResourceNotFoundError,
110
+ InvalidInputError,
111
+ ValidationError,
112
+ DatabaseError,
113
+ UniqueConstraintError,
114
+ UnknownError,
115
+ ForeignKeyConstraintError,
116
+ OperationNotAllowedError,
117
+ AuthenticationError,
118
+ AuthorizationError,
119
+ };
120
+ export type { NetworkError, ForbiddenError };
121
+
122
+ export interface ApiErrorResponse {
123
+ code:
124
+ | "not_found"
125
+ | "gone"
126
+ | "bad_request"
127
+ | "internal_server_error"
128
+ | "unauthorized"
129
+ | "method_not_allowed"
130
+ | "not_authenticated"
131
+ | "forbidden"
132
+ | "network_error";
133
+ message: string;
134
+ status: number;
135
+ url: URL;
136
+ details?: Record<string, string | string[] | number | number[] | boolean | boolean[]>;
137
+ responseMessage?: string;
138
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./jwt";
2
+ export * from "./env";
package/src/lib/jwt.ts ADDED
@@ -0,0 +1,113 @@
1
+ import jwt, { JwtPayload } from "jsonwebtoken";
2
+ import { symmetricDecrypt, symmetricEncrypt } from "./crypto";
3
+ import { getEnv } from "./env";
4
+
5
+ export const createToken = (userId: string, userEmail: string, options = {}): string => {
6
+ const encryptedUserId = symmetricEncrypt(userId, getEnv().ENCRYPTION_KEY);
7
+ return jwt.sign({ id: encryptedUserId }, getEnv().NEXTAUTH_SECRET + userEmail, options);
8
+ };
9
+ export const createTokenForLinkSurvey = (surveyId: string, userEmail: string): string => {
10
+ const encryptedEmail = symmetricEncrypt(userEmail, getEnv().ENCRYPTION_KEY);
11
+ return jwt.sign({ email: encryptedEmail }, getEnv().NEXTAUTH_SECRET + surveyId);
12
+ };
13
+
14
+ export const createEmailToken = (email: string): string => {
15
+ const encryptedEmail = symmetricEncrypt(email, getEnv().ENCRYPTION_KEY);
16
+ return jwt.sign({ email: encryptedEmail }, getEnv().NEXTAUTH_SECRET);
17
+ };
18
+
19
+ export const getEmailFromEmailToken = (token: string): string => {
20
+ const payload = jwt.verify(token, getEnv().NEXTAUTH_SECRET) as JwtPayload;
21
+ try {
22
+ // Try to decrypt first (for newer tokens)
23
+ const decryptedEmail = symmetricDecrypt(payload.email, getEnv().ENCRYPTION_KEY);
24
+ return decryptedEmail;
25
+ } catch {
26
+ // If decryption fails, return the original email (for older tokens)
27
+ return payload.email;
28
+ }
29
+ };
30
+
31
+ export const createInviteToken = (inviteId: string, email: string, options = {}): string => {
32
+ const encryptedInviteId = symmetricEncrypt(inviteId, getEnv().ENCRYPTION_KEY);
33
+ const encryptedEmail = symmetricEncrypt(email, getEnv().ENCRYPTION_KEY);
34
+ return jwt.sign({ inviteId: encryptedInviteId, email: encryptedEmail }, getEnv().NEXTAUTH_SECRET, options);
35
+ };
36
+
37
+ export const verifyTokenForLinkSurvey = (token: string, surveyId: string): string | null => {
38
+ try {
39
+ const { email } = jwt.verify(token, getEnv().NEXTAUTH_SECRET + surveyId) as JwtPayload;
40
+ try {
41
+ // Try to decrypt first (for newer tokens)
42
+ const decryptedEmail = symmetricDecrypt(email, getEnv().ENCRYPTION_KEY);
43
+ return decryptedEmail;
44
+ } catch {
45
+ // If decryption fails, return the original email (for older tokens)
46
+ return email;
47
+ }
48
+ } catch (err) {
49
+ return null;
50
+ }
51
+ };
52
+
53
+ export const verifyToken = async (token: string): Promise<JwtPayload> => {
54
+ // First decode to get the ID
55
+ const decoded = jwt.decode(token);
56
+ const payload: JwtPayload = decoded as JwtPayload;
57
+
58
+ const { id } = payload;
59
+ if (!id) {
60
+ throw new Error("Token missing required field: id");
61
+ }
62
+
63
+ // Try to decrypt the ID (for newer tokens), if it fails use the ID as-is (for older tokens)
64
+ let decryptedId: string;
65
+ try {
66
+ decryptedId = symmetricDecrypt(id, getEnv().ENCRYPTION_KEY);
67
+ } catch {
68
+ decryptedId = id;
69
+ }
70
+
71
+ // If no email provided, look up the user
72
+ const foundUser: any = null;/* await prisma.user.findUnique({
73
+ where: { id: decryptedId },
74
+ }); */
75
+
76
+ if (!foundUser) {
77
+ throw new Error("User not found");
78
+ }
79
+
80
+ const userEmail = foundUser.email;
81
+
82
+ return { id: decryptedId, email: userEmail };
83
+ };
84
+
85
+ export const verifyInviteToken = (token: string): { inviteId: string; email: string } => {
86
+ try {
87
+ const decoded = jwt.decode(token);
88
+ const payload: JwtPayload = decoded as JwtPayload;
89
+
90
+ const { inviteId, email } = payload;
91
+
92
+ let decryptedInviteId: string;
93
+ let decryptedEmail: string;
94
+
95
+ try {
96
+ // Try to decrypt first (for newer tokens)
97
+ decryptedInviteId = symmetricDecrypt(inviteId, getEnv().ENCRYPTION_KEY);
98
+ decryptedEmail = symmetricDecrypt(email, getEnv().ENCRYPTION_KEY);
99
+ } catch {
100
+ // If decryption fails, use original values (for older tokens)
101
+ decryptedInviteId = inviteId;
102
+ decryptedEmail = email;
103
+ }
104
+
105
+ return {
106
+ inviteId: decryptedInviteId,
107
+ email: decryptedEmail,
108
+ };
109
+ } catch (error) {
110
+ console.error(`Error verifying invite token: ${error}`);
111
+ throw new Error("Invalid or expired invite token");
112
+ }
113
+ };