@stamhoofd/backend 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 (150) hide show
  1. package/.env.template.json +63 -0
  2. package/.eslintrc.js +61 -0
  3. package/README.md +40 -0
  4. package/index.ts +172 -0
  5. package/jest.config.js +11 -0
  6. package/migrations.ts +33 -0
  7. package/package.json +48 -0
  8. package/src/crons.ts +845 -0
  9. package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +42 -0
  10. package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +320 -0
  11. package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +171 -0
  12. package/src/endpoints/auth/CreateAdminEndpoint.ts +137 -0
  13. package/src/endpoints/auth/CreateTokenEndpoint.test.ts +68 -0
  14. package/src/endpoints/auth/CreateTokenEndpoint.ts +200 -0
  15. package/src/endpoints/auth/DeleteTokenEndpoint.ts +31 -0
  16. package/src/endpoints/auth/ForgotPasswordEndpoint.ts +70 -0
  17. package/src/endpoints/auth/GetUserEndpoint.test.ts +64 -0
  18. package/src/endpoints/auth/GetUserEndpoint.ts +57 -0
  19. package/src/endpoints/auth/PatchApiUserEndpoint.ts +90 -0
  20. package/src/endpoints/auth/PatchUserEndpoint.ts +122 -0
  21. package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +37 -0
  22. package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +41 -0
  23. package/src/endpoints/auth/SignupEndpoint.ts +107 -0
  24. package/src/endpoints/auth/VerifyEmailEndpoint.ts +89 -0
  25. package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +95 -0
  26. package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +31 -0
  27. package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +101 -0
  28. package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +53 -0
  29. package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +57 -0
  30. package/src/endpoints/global/files/UploadFile.ts +147 -0
  31. package/src/endpoints/global/files/UploadImage.ts +119 -0
  32. package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +76 -0
  33. package/src/endpoints/global/members/GetMembersCountEndpoint.ts +43 -0
  34. package/src/endpoints/global/members/GetMembersEndpoint.ts +429 -0
  35. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +734 -0
  36. package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +45 -0
  37. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +105 -0
  38. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +146 -0
  39. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.test.ts +52 -0
  40. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +80 -0
  41. package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +49 -0
  42. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.test.ts +58 -0
  43. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +62 -0
  44. package/src/endpoints/global/payments/ExchangeSTPaymentEndpoint.ts +153 -0
  45. package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +134 -0
  46. package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +44 -0
  47. package/src/endpoints/global/platform/GetPlatformEnpoint.ts +39 -0
  48. package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +63 -0
  49. package/src/endpoints/global/registration/GetPaymentRegistrations.ts +68 -0
  50. package/src/endpoints/global/registration/GetUserBalanceEndpoint.ts +39 -0
  51. package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +80 -0
  52. package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +41 -0
  53. package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +134 -0
  54. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +521 -0
  55. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +37 -0
  56. package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +115 -0
  57. package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +187 -0
  58. package/src/endpoints/organization/dashboard/billing/ActivatePackagesEndpoint.ts +424 -0
  59. package/src/endpoints/organization/dashboard/billing/DeactivatePackageEndpoint.ts +67 -0
  60. package/src/endpoints/organization/dashboard/billing/GetBillingStatusEndpoint.ts +39 -0
  61. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +57 -0
  62. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +50 -0
  63. package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +50 -0
  64. package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +129 -0
  65. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplateEndpoint.ts +114 -0
  66. package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +50 -0
  67. package/src/endpoints/organization/dashboard/email/EmailEndpoint.ts +234 -0
  68. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +62 -0
  69. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +85 -0
  70. package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +80 -0
  71. package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +54 -0
  72. package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +49 -0
  73. package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +63 -0
  74. package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +61 -0
  75. package/src/endpoints/organization/dashboard/organization/ApplyRegisterCodeEndpoint.test.ts +64 -0
  76. package/src/endpoints/organization/dashboard/organization/ApplyRegisterCodeEndpoint.ts +84 -0
  77. package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +43 -0
  78. package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +42 -0
  79. package/src/endpoints/organization/dashboard/organization/GetOrganizationSSOEndpoint.ts +43 -0
  80. package/src/endpoints/organization/dashboard/organization/GetRegisterCodeEndpoint.ts +65 -0
  81. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +281 -0
  82. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +338 -0
  83. package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +196 -0
  84. package/src/endpoints/organization/dashboard/organization/SetOrganizationSSOEndpoint.ts +50 -0
  85. package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +48 -0
  86. package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +207 -0
  87. package/src/endpoints/organization/dashboard/payments/PatchBalanceItemsEndpoint.ts +202 -0
  88. package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +233 -0
  89. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +66 -0
  90. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +210 -0
  91. package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +93 -0
  92. package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +59 -0
  93. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +78 -0
  94. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +40 -0
  95. package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +69 -0
  96. package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +52 -0
  97. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +73 -0
  98. package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +60 -0
  99. package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +47 -0
  100. package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +41 -0
  101. package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +217 -0
  102. package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +51 -0
  103. package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +47 -0
  104. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +83 -0
  105. package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +68 -0
  106. package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +69 -0
  107. package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +125 -0
  108. package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +204 -0
  109. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +278 -0
  110. package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +80 -0
  111. package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +60 -0
  112. package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +379 -0
  113. package/src/endpoints/organization/shared/GetDocumentHtml.ts +54 -0
  114. package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +45 -0
  115. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.test.ts +78 -0
  116. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +34 -0
  117. package/src/endpoints/organization/shared/auth/OpenIDConnectCallbackEndpoint.ts +44 -0
  118. package/src/endpoints/organization/shared/auth/OpenIDConnectStartEndpoint.ts +82 -0
  119. package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +59 -0
  120. package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +51 -0
  121. package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +40 -0
  122. package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +124 -0
  123. package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +130 -0
  124. package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +50 -0
  125. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +450 -0
  126. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +335 -0
  127. package/src/helpers/AddressValidator.test.ts +40 -0
  128. package/src/helpers/AddressValidator.ts +256 -0
  129. package/src/helpers/AdminPermissionChecker.ts +1031 -0
  130. package/src/helpers/AuthenticatedStructures.ts +158 -0
  131. package/src/helpers/BuckarooHelper.ts +279 -0
  132. package/src/helpers/CheckSettlements.ts +215 -0
  133. package/src/helpers/Context.ts +202 -0
  134. package/src/helpers/CookieHelper.ts +45 -0
  135. package/src/helpers/ForwardHandler.test.ts +216 -0
  136. package/src/helpers/ForwardHandler.ts +140 -0
  137. package/src/helpers/OpenIDConnectHelper.ts +284 -0
  138. package/src/helpers/StripeHelper.ts +293 -0
  139. package/src/helpers/StripePayoutChecker.ts +188 -0
  140. package/src/middleware/ContextMiddleware.ts +16 -0
  141. package/src/migrations/1646578856-validate-addresses.ts +60 -0
  142. package/src/seeds/0000000000-example.ts +13 -0
  143. package/src/seeds/1715028563-user-permissions.ts +52 -0
  144. package/tests/e2e/stock.test.ts +2120 -0
  145. package/tests/e2e/tickets.test.ts +926 -0
  146. package/tests/helpers/StripeMocker.ts +362 -0
  147. package/tests/helpers/TestServer.ts +21 -0
  148. package/tests/jest.global.setup.ts +29 -0
  149. package/tests/jest.setup.ts +59 -0
  150. package/tsconfig.json +42 -0
@@ -0,0 +1,188 @@
1
+ import {Order, Payment, StripeCheckoutSession, StripePaymentIntent} from "@stamhoofd/models";
2
+ import { Settlement } from "@stamhoofd/structures";
3
+ import Stripe from "stripe";
4
+
5
+ export class StripePayoutChecker {
6
+ private stripe: Stripe;
7
+ private stripePlatform: Stripe;
8
+
9
+ constructor({secretKey, stripeAccount}: { secretKey: string, stripeAccount?: string}) {
10
+ this.stripe = new Stripe(
11
+ secretKey, {
12
+ apiVersion: '2022-11-15',
13
+ typescript: true,
14
+ maxNetworkRetries: 1,
15
+ timeout: 10000,
16
+ stripeAccount
17
+ });
18
+
19
+ this.stripePlatform = new Stripe(
20
+ secretKey, {
21
+ apiVersion: '2022-11-15',
22
+ typescript: true,
23
+ maxNetworkRetries: 1,
24
+ timeout: 10000
25
+ });
26
+
27
+ }
28
+
29
+ async checkSettlements(checkAll = false) {
30
+ // Check last 2 weeks + 3 day margin, unless we check them all
31
+ const d = new Date()
32
+ d.setDate(d.getDate() - 17)
33
+
34
+ if (checkAll) {
35
+ d.setFullYear(2022, 11, 1)
36
+ }
37
+
38
+ // Loop all payouts
39
+ try {
40
+ // Fetch all payouts that are paid out
41
+ for await (const payout of this.stripe.payouts.list({
42
+ status: 'paid',
43
+ arrival_date: {
44
+ gte: Math.floor(d.getTime() / 1000)
45
+ }
46
+ })) {
47
+ // Get all payments for this payout
48
+ await this.fetchBalanceItems(payout);
49
+ }
50
+
51
+ } catch (e) {
52
+ console.error(e)
53
+ }
54
+ }
55
+
56
+ private async fetchBalanceItems(payout: Stripe.Payout) {
57
+ // For the given payout, fetch all balance items
58
+ const params = {
59
+ payout: payout.id,
60
+ // Via the Application Fee object, we can get the original payment metadata
61
+ expand: ['data.source', 'data.source.application_fee', 'data.source.application_fee.originating_transaction'],
62
+ // TODO: ALSO DO CARDS! (type: 'charge')
63
+ //type: 'payment'
64
+ };
65
+
66
+ for await (const balanceItem of this.stripe.balanceTransactions.list(params)) {
67
+ // TODO
68
+
69
+ if (balanceItem.type === 'charge' || balanceItem.type === 'payment') {
70
+ await this.handleBalanceItem(payout, balanceItem);
71
+ }
72
+ }
73
+
74
+ return;
75
+ }
76
+
77
+ private async handleBalanceItem(payout: Stripe.Payout, balanceItem: Stripe.BalanceTransaction) {
78
+ if (!balanceItem.source || typeof balanceItem.source === 'string') {
79
+ return;
80
+ }
81
+ if (balanceItem.source.object !== 'charge') {
82
+ console.log("No payment id set for charge " + balanceItem.source.id)
83
+ return;
84
+ }
85
+
86
+ let paymentId = balanceItem.source.metadata.payment;
87
+
88
+ if (!paymentId) {
89
+ // Search in the metadata of the application fee, originating transaction
90
+ if (typeof balanceItem.source.application_fee !== 'string' && balanceItem.source.application_fee) {
91
+ const applicationFee = balanceItem.source.application_fee;
92
+
93
+ if (applicationFee.originating_transaction !== 'string' && applicationFee.originating_transaction) {
94
+ const originatingTransaction = applicationFee.originating_transaction as Stripe.Charge;
95
+ paymentId = originatingTransaction.metadata.payment;
96
+
97
+ if (!paymentId) {
98
+ // Historical bug where we didn't save payment in metadata
99
+ // Try to look it up by payment intent id
100
+
101
+ if (originatingTransaction.payment_intent) {
102
+ const paymentIntentId = typeof originatingTransaction.payment_intent === 'string' ? originatingTransaction.payment_intent : originatingTransaction.payment_intent.id
103
+ const stripePayments = await StripePaymentIntent.where({
104
+ stripeIntentId: paymentIntentId
105
+ }, {limit: 1});
106
+
107
+ if (stripePayments.length === 1) {
108
+ paymentId = stripePayments[0].paymentId;
109
+ console.log("Found missing payment metadata for payment intent "+originatingTransaction.payment_intent, paymentId)
110
+ } else {
111
+ // Probably a card payment
112
+ // Search for the checkout session
113
+ const checkoutSession = await this.stripePlatform.checkout.sessions.list({
114
+ payment_intent: paymentIntentId
115
+ })
116
+ if (checkoutSession.data.length === 1) {
117
+ const session = checkoutSession.data[0];
118
+ console.log("Found checkout session for payment intent ", paymentIntentId, session)
119
+
120
+ // Search
121
+ const stripeCheckoutSessions = await StripeCheckoutSession.where({
122
+ stripeSessionId: session.id
123
+ }, {limit: 1});
124
+
125
+ if (stripeCheckoutSessions.length === 1) {
126
+ paymentId = stripeCheckoutSessions[0].paymentId;
127
+ console.log("Found missing payment metadata for payment intent "+originatingTransaction.payment_intent, paymentId)
128
+ } else {
129
+ console.log("No payment found for checkout session "+session.id)
130
+ }
131
+ } else {
132
+ console.log("No Stripe Checkout Sessions found for payment intent "+paymentIntentId)
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
138
+
139
+
140
+ }
141
+ }
142
+
143
+ if (!paymentId) {
144
+ console.log(balanceItem)
145
+ console.log("No payment id set for charge " + balanceItem.source.id)
146
+ return;
147
+ }
148
+
149
+ const applicationFee = balanceItem.source.application_fee_amount;
150
+
151
+ // Cool, we can store this in the database now.
152
+
153
+ const payment = await Payment.getByID(paymentId);
154
+ if (!payment) {
155
+ console.log("Invalid payment id set for charge " + balanceItem.source.id+': '+paymentId)
156
+ return;
157
+ }
158
+
159
+ if (payment.price !== balanceItem.amount) {
160
+ console.log("Amount mismatch for payment " + payment.id+': '+payment.price+' !== '+balanceItem.amount)
161
+ return;
162
+ }
163
+
164
+ const settlement = Settlement.create({
165
+ id: payout.id,
166
+ reference: payout.statement_descriptor ?? '',
167
+ settledAt: new Date(payout.arrival_date * 1000),
168
+ amount: payout.amount,
169
+ // Set only if application fee is witheld
170
+ fee: applicationFee ?? 0
171
+ });
172
+
173
+ payment.settlement = settlement;
174
+ payment.transferFee = applicationFee ?? 0;
175
+
176
+ // Force an updatedAt timestamp of the related order
177
+ // Mark order as 'updated', or the frontend won't pull in the updates
178
+ const order = await Order.getForPayment(null, payment.id)
179
+ if (order) {
180
+ order.updatedAt = new Date();
181
+ order.forceSaveProperty('updatedAt');
182
+ await order.save();
183
+ }
184
+
185
+ await payment.save();
186
+ }
187
+
188
+ }
@@ -0,0 +1,16 @@
1
+ import { Request, RequestMiddleware } from "@simonbackx/simple-endpoints"
2
+
3
+ import { ContextInstance } from "../helpers/Context"
4
+
5
+ /**
6
+ * This attaches a context to each request for authentication and authorization
7
+ */
8
+ export const ContextMiddleware: RequestMiddleware = {
9
+ wrapRun<T>(run: () => Promise<T>, request: Request) {
10
+ return ContextInstance.start(request, run)
11
+ },
12
+
13
+ handleRequest: function (request: Request) {
14
+ // Noop
15
+ }
16
+ }
@@ -0,0 +1,60 @@
1
+ import { Migration } from '@simonbackx/simple-database';
2
+
3
+
4
+ export default new Migration(async () => {
5
+ if (STAMHOOFD.environment == "test") {
6
+ console.log("skipped in tests")
7
+ return;
8
+ }
9
+
10
+ return Promise.resolve()
11
+
12
+ /*let lastId = ""
13
+
14
+ while(true) {
15
+ const members = await Member.where({
16
+ id: {
17
+ sign: ">",
18
+ value: lastId
19
+ },
20
+ }, {
21
+ limit: 100,
22
+ sort: ["id"]
23
+ })
24
+
25
+ if (members.length == 0) {
26
+ return
27
+ }
28
+
29
+ lastId = members[members.length - 1].id
30
+
31
+ for (const member of members) {
32
+ if (member.details) {
33
+ const addresses = [member.details.address, ...member.details.parents.map(p => p.address)].filter(a => a !== null) as Address[]
34
+
35
+ for (const address of addresses) {
36
+ try {
37
+ const validatedAddress = await AddressValidator.validate(address)
38
+ const s = address.toString()
39
+ const e = validatedAddress.toString()
40
+ if (s != e) {
41
+ if (StringCompare.typoCount(address.street, validatedAddress.street) > 4) {
42
+ console.log("Updated street: " + s + " => " + e)
43
+ }
44
+ if (StringCompare.typoCount(address.city, validatedAddress.city) > 4) {
45
+ //console.log("Updated city: " + s + " => " + e)
46
+ }
47
+ }
48
+ } catch (e) {
49
+ console.error("Invalid address: " + address.toString()+" — "+e.message)
50
+ }
51
+ }
52
+
53
+ }
54
+ }
55
+ }
56
+
57
+ throw new Error("WIP")*/
58
+ });
59
+
60
+
@@ -0,0 +1,13 @@
1
+ import { Migration } from '@simonbackx/simple-database';
2
+
3
+ export default new Migration(async () => {
4
+ if (STAMHOOFD.environment == "test") {
5
+ console.log("skipped in tests")
6
+ return;
7
+ }
8
+
9
+ // Do something here
10
+ return Promise.resolve()
11
+ });
12
+
13
+
@@ -0,0 +1,52 @@
1
+ import { Migration } from '@simonbackx/simple-database';
2
+ import { User } from '@stamhoofd/models';
3
+ import { UserPermissions } from '@stamhoofd/structures';
4
+
5
+ export default new Migration(async () => {
6
+ if (STAMHOOFD.environment == "test") {
7
+ console.log("skipped in tests")
8
+ return;
9
+ }
10
+ process.stdout.write('\n');
11
+ let c = 0;
12
+ while(true) {
13
+ const admins = await User.where({
14
+ organizationPermissions: {
15
+ value: null,
16
+ sign: '!='
17
+ },
18
+ organizationId: {
19
+ value: null,
20
+ sign: '!='
21
+ }
22
+ }, {limit: 100})
23
+
24
+ for (const admin of admins) {
25
+ if (!admin.organizationPermissions || !admin.organizationId) {
26
+ continue
27
+ }
28
+ const p = UserPermissions.create({})
29
+ p.organizationPermissions.set(admin.organizationId, admin.organizationPermissions)
30
+ admin.permissions = UserPermissions.limitedAdd(admin.permissions, p, admin.organizationId)
31
+ admin.organizationPermissions = null
32
+ await admin.save()
33
+ c++;
34
+
35
+ if (c%1000 === 0) {
36
+ process.stdout.write('.');
37
+ }
38
+ if (c%10000 === 0) {
39
+ process.stdout.write('\n');
40
+ }
41
+ }
42
+
43
+ if (admins.length === 0) {
44
+ break;
45
+ }
46
+ }
47
+
48
+ // Do something here
49
+ return Promise.resolve()
50
+ });
51
+
52
+