@verii/endpoints-organizations-registrar 1.0.0-pre.1752076816

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 (259) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +1 -0
  3. package/README.md +3 -0
  4. package/package.json +86 -0
  5. package/src/config/abi.json +1 -0
  6. package/src/config/config.js +261 -0
  7. package/src/controllers/consents/autohooks.js +6 -0
  8. package/src/controllers/consents/controller.js +106 -0
  9. package/src/controllers/consents/schemas/consent-response.schema.js +45 -0
  10. package/src/controllers/did-web-host/controller.js +64 -0
  11. package/src/controllers/groups/autohooks.js +10 -0
  12. package/src/controllers/groups/controller.js +172 -0
  13. package/src/controllers/groups/schemas/group.schema.json +22 -0
  14. package/src/controllers/groups/schemas/index.js +7 -0
  15. package/src/controllers/groups/schemas/modify-group.schema.json +25 -0
  16. package/src/controllers/image_upload/controller.js +48 -0
  17. package/src/controllers/invitations/controller.js +79 -0
  18. package/src/controllers/organizations/_did/autohooks.js +16 -0
  19. package/src/controllers/organizations/_did/controller.js +617 -0
  20. package/src/controllers/organizations/_did/invitations/_invitationId/autohooks.js +16 -0
  21. package/src/controllers/organizations/_did/invitations/_invitationId/controller.js +217 -0
  22. package/src/controllers/organizations/_did/invitations/controller.js +197 -0
  23. package/src/controllers/organizations/_did/keys/controller.js +141 -0
  24. package/src/controllers/organizations/_did/services/controller.js +195 -0
  25. package/src/controllers/organizations/_did/signatories/controller.js +63 -0
  26. package/src/controllers/organizations/autohooks.js +65 -0
  27. package/src/controllers/organizations/controller.js +322 -0
  28. package/src/controllers/organizations/full/controller.js +285 -0
  29. package/src/controllers/organizations/plugins.js +21 -0
  30. package/src/controllers/organizations/schemas/add-key-body.schema.json +35 -0
  31. package/src/controllers/organizations/schemas/create-did-service.schema.json +70 -0
  32. package/src/controllers/organizations/schemas/did-key.schema.json +178 -0
  33. package/src/controllers/organizations/schemas/full-organization.schema.json +35 -0
  34. package/src/controllers/organizations/schemas/index.js +33 -0
  35. package/src/controllers/organizations/schemas/invitationCodeProperty.schema.json +3 -0
  36. package/src/controllers/organizations/schemas/organization-ids.schema.json +34 -0
  37. package/src/controllers/organizations/schemas/organization-kyb-profile-creation.schema.json +26 -0
  38. package/src/controllers/organizations/schemas/organization-profile-creation.schema.json +20 -0
  39. package/src/controllers/organizations/schemas/organization-profile-update.schema.json +19 -0
  40. package/src/controllers/organizations/schemas/organization-profile-verifiable-credential.schema.json +25 -0
  41. package/src/controllers/organizations/schemas/organization-registry-service-response.schema.json +26 -0
  42. package/src/controllers/organizations/schemas/organization-service.schema.json +34 -0
  43. package/src/controllers/organizations/schemas/organization-verified-profile.schema.json +123 -0
  44. package/src/controllers/organizations/schemas/organization.search-profile.query-params.schema.json +50 -0
  45. package/src/controllers/organizations/schemas/organization.search.query-params.schema.json +42 -0
  46. package/src/controllers/reference/controller.js +103 -0
  47. package/src/controllers/resolve-did/controller.js +45 -0
  48. package/src/controllers/resolve-did/resolve-did.js +30 -0
  49. package/src/controllers/resolve-did/schemas/did-doc.schema.json +155 -0
  50. package/src/controllers/resolve-did/schemas/did-proof.schema.json +44 -0
  51. package/src/controllers/resolve-did/schemas/index.js +26 -0
  52. package/src/controllers/resolve-did/schemas/public-key.schema.json +173 -0
  53. package/src/controllers/resolve-kid/controller.js +76 -0
  54. package/src/controllers/resolve-kid/public-key-formats.js +8 -0
  55. package/src/controllers/service-types/controller.js +81 -0
  56. package/src/controllers/setup_image_upload/controller.js +99 -0
  57. package/src/controllers/signatories/controller.js +43 -0
  58. package/src/controllers/users/autohooks.js +10 -0
  59. package/src/controllers/users/controller.js +221 -0
  60. package/src/controllers/users/schemas/base-user.schema.json +55 -0
  61. package/src/controllers/users/schemas/index.js +4 -0
  62. package/src/controllers/users/schemas/modify-user.schema.js +17 -0
  63. package/src/controllers/users/schemas/user.schema.js +20 -0
  64. package/src/entities/groups/domain/constants.js +21 -0
  65. package/src/entities/groups/domain/index.js +19 -0
  66. package/src/entities/groups/factories/groups-factory.js +48 -0
  67. package/src/entities/groups/factories/index.js +17 -0
  68. package/src/entities/groups/index.js +19 -0
  69. package/src/entities/groups/repo.js +122 -0
  70. package/src/entities/images/domain/constant.js +11 -0
  71. package/src/entities/images/domain/index.js +3 -0
  72. package/src/entities/images/extension/activate.extension.js +35 -0
  73. package/src/entities/images/extension/deactivate.extension.js +27 -0
  74. package/src/entities/images/extension/find-by-url.extension.js +24 -0
  75. package/src/entities/images/extension/index.js +5 -0
  76. package/src/entities/images/factories/images-factory.js +43 -0
  77. package/src/entities/images/factories/index.js +17 -0
  78. package/src/entities/images/index.js +5 -0
  79. package/src/entities/images/repo.js +43 -0
  80. package/src/entities/images/schema/image-metadata.schema.js +58 -0
  81. package/src/entities/images/schema/index.js +3 -0
  82. package/src/entities/index.js +31 -0
  83. package/src/entities/invitations/domains/build-invitation-url.js +14 -0
  84. package/src/entities/invitations/domains/get-given-family-name-from-name.js +20 -0
  85. package/src/entities/invitations/domains/index.js +7 -0
  86. package/src/entities/invitations/domains/init-invitation-emails.js +17 -0
  87. package/src/entities/invitations/domains/is-invitation-expired.js +5 -0
  88. package/src/entities/invitations/domains/validate-invitee-email.js +18 -0
  89. package/src/entities/invitations/factories/index.js +17 -0
  90. package/src/entities/invitations/factories/invitations-factory.js +51 -0
  91. package/src/entities/invitations/index.js +6 -0
  92. package/src/entities/invitations/orchestrators/accept-invitation.js +24 -0
  93. package/src/entities/invitations/orchestrators/index.js +4 -0
  94. package/src/entities/invitations/orchestrators/send-email-invitee.js +36 -0
  95. package/src/entities/invitations/repo.js +37 -0
  96. package/src/entities/invitations/schemas/add-invitation-body.js +122 -0
  97. package/src/entities/invitations/schemas/get-invitation-response-body.js +20 -0
  98. package/src/entities/invitations/schemas/index.js +5 -0
  99. package/src/entities/invitations/schemas/invitation-response-item-body.js +61 -0
  100. package/src/entities/kms/factories/index.js +17 -0
  101. package/src/entities/kms/factories/kms-factory.js +31 -0
  102. package/src/entities/monitors/index.js +17 -0
  103. package/src/entities/monitors/orchestrators/index.js +17 -0
  104. package/src/entities/monitors/orchestrators/monitors.js +230 -0
  105. package/src/entities/oauth/domain/constants.js +23 -0
  106. package/src/entities/oauth/domain/index.js +5 -0
  107. package/src/entities/oauth/domain/roles.js +92 -0
  108. package/src/entities/oauth/domain/scopes.js +35 -0
  109. package/src/entities/oauth/index.js +4 -0
  110. package/src/entities/oauth/orchestrators/auth0-provisioner.js +293 -0
  111. package/src/entities/oauth/orchestrators/index.js +3 -0
  112. package/src/entities/organization-keys/domains/build-organization-key.js +50 -0
  113. package/src/entities/organization-keys/domains/constants.js +30 -0
  114. package/src/entities/organization-keys/domains/extract-verification-method-from-byo-did-document.js +38 -0
  115. package/src/entities/organization-keys/domains/find-key-by-purpose.js +6 -0
  116. package/src/entities/organization-keys/domains/index.js +10 -0
  117. package/src/entities/organization-keys/domains/jwk-to-hex-key-transformer.js +13 -0
  118. package/src/entities/organization-keys/domains/map-key-response.js +29 -0
  119. package/src/entities/organization-keys/domains/validate-non-custodial-key.js +11 -0
  120. package/src/entities/organization-keys/domains/validate-organization-key.js +42 -0
  121. package/src/entities/organization-keys/factories/index.js +17 -0
  122. package/src/entities/organization-keys/factories/organization-keys-factory.js +55 -0
  123. package/src/entities/organization-keys/index.js +5 -0
  124. package/src/entities/organization-keys/orchestrators/add-key-to-did-doc.js +19 -0
  125. package/src/entities/organization-keys/orchestrators/add-key.js +155 -0
  126. package/src/entities/organization-keys/orchestrators/add-operator-keys.js +46 -0
  127. package/src/entities/organization-keys/orchestrators/delete-key.js +93 -0
  128. package/src/entities/organization-keys/orchestrators/get-key.js +39 -0
  129. package/src/entities/organization-keys/orchestrators/index.js +24 -0
  130. package/src/entities/organization-keys/orchestrators/resolve-verification-method-byo-did.js +28 -0
  131. package/src/entities/organization-keys/repos/repo.js +48 -0
  132. package/src/entities/organization-services/adapters/index.js +21 -0
  133. package/src/entities/organization-services/adapters/init-provision-auth0-client-grants.js +44 -0
  134. package/src/entities/organization-services/adapters/init-provision-auth0-clients.js +56 -0
  135. package/src/entities/organization-services/adapters/update-blockchain-permissions-from-permitted-services.js +118 -0
  136. package/src/entities/organization-services/domains/activate-services.js +12 -0
  137. package/src/entities/organization-services/domains/build-organizations-services.js +38 -0
  138. package/src/entities/organization-services/domains/build-public-services.js +19 -0
  139. package/src/entities/organization-services/domains/constants.js +32 -0
  140. package/src/entities/organization-services/domains/extract-cao-service-refs.js +10 -0
  141. package/src/entities/organization-services/domains/extract-service-endpoint-did.js +10 -0
  142. package/src/entities/organization-services/domains/get-service-consent-type.js +16 -0
  143. package/src/entities/organization-services/domains/get-service-types-from-categories.js +18 -0
  144. package/src/entities/organization-services/domains/index.js +17 -0
  145. package/src/entities/organization-services/domains/is-new-node-operator-service.js +25 -0
  146. package/src/entities/organization-services/domains/is-service-category.js +31 -0
  147. package/src/entities/organization-services/domains/normalize-service-endpoint.js +6 -0
  148. package/src/entities/organization-services/domains/select-activated-services.js +8 -0
  149. package/src/entities/organization-services/domains/transform-profile-service.js +88 -0
  150. package/src/entities/organization-services/domains/validate-cao-service-refs.js +25 -0
  151. package/src/entities/organization-services/domains/validate-service-credential-type.js +47 -0
  152. package/src/entities/organization-services/domains/validate-service-endpoint.js +35 -0
  153. package/src/entities/organization-services/domains/validate-service-fields-by-service-type.js +37 -0
  154. package/src/entities/organization-services/domains/validate-service-id-uniqueness.js +19 -0
  155. package/src/entities/organization-services/domains/validate-service-key-purposes.js +56 -0
  156. package/src/entities/organization-services/domains/validate-service-type.js +12 -0
  157. package/src/entities/organization-services/domains/validate-service.js +80 -0
  158. package/src/entities/organization-services/domains/validate-services-for-delete.js +32 -0
  159. package/src/entities/organization-services/index.js +5 -0
  160. package/src/entities/organization-services/orchestrators/add-service.js +106 -0
  161. package/src/entities/organization-services/orchestrators/delete-service.js +142 -0
  162. package/src/entities/organization-services/orchestrators/get-service.js +36 -0
  163. package/src/entities/organization-services/orchestrators/index.js +8 -0
  164. package/src/entities/organization-services/orchestrators/init-add-service-to-organization.js +141 -0
  165. package/src/entities/organization-services/orchestrators/load-cao-service-refs.js +56 -0
  166. package/src/entities/organization-services/orchestrators/update-service.js +103 -0
  167. package/src/entities/organizations/adapters/index.js +6 -0
  168. package/src/entities/organizations/adapters/init-organization-registrar-emails.js +215 -0
  169. package/src/entities/organizations/adapters/init-send-activation-emails-to-caos.js +89 -0
  170. package/src/entities/organizations/adapters/send-email-invitation-accepted-to-inviter.js +70 -0
  171. package/src/entities/organizations/adapters/send-email-notifications.js +212 -0
  172. package/src/entities/organizations/domains/build-custodied-did-web.js +12 -0
  173. package/src/entities/organizations/domains/build-full-organization-response.js +40 -0
  174. package/src/entities/organizations/domains/build-organization-modifications-on-service-change.js +82 -0
  175. package/src/entities/organizations/domains/build-profile-vc-url.js +8 -0
  176. package/src/entities/organizations/domains/build-profile-verifiable-credential.js +36 -0
  177. package/src/entities/organizations/domains/build-public-profile.js +9 -0
  178. package/src/entities/organizations/domains/constants.js +54 -0
  179. package/src/entities/organizations/domains/index.js +17 -0
  180. package/src/entities/organizations/domains/organization-vc-checks.js +49 -0
  181. package/src/entities/organizations/domains/parse-profile-to-csv.js +41 -0
  182. package/src/entities/organizations/domains/prepare-profile-vc.js +28 -0
  183. package/src/entities/organizations/domains/profile-name-normalization.js +5 -0
  184. package/src/entities/organizations/domains/validate-byo-did-keys.js +28 -0
  185. package/src/entities/organizations/domains/validate-profile-name.js +48 -0
  186. package/src/entities/organizations/domains/validate-profile-website.js +17 -0
  187. package/src/entities/organizations/domains/validate-update-profile.js +11 -0
  188. package/src/entities/organizations/factories/index.js +17 -0
  189. package/src/entities/organizations/factories/organizations-factory.js +180 -0
  190. package/src/entities/organizations/index.js +6 -0
  191. package/src/entities/organizations/orchestrators/add-primary-permissions.js +28 -0
  192. package/src/entities/organizations/orchestrators/build-custodied-organization.js +92 -0
  193. package/src/entities/organizations/orchestrators/build-non-custodied-organization.js +83 -0
  194. package/src/entities/organizations/orchestrators/index.js +6 -0
  195. package/src/entities/organizations/orchestrators/init-create-organization.js +221 -0
  196. package/src/entities/organizations/orchestrators/init-provision-group.js +48 -0
  197. package/src/entities/organizations/orchestrators/verify-profile-website-unique.js +15 -0
  198. package/src/entities/organizations/repos/find-caos-extension.js +49 -0
  199. package/src/entities/organizations/repos/index.js +17 -0
  200. package/src/entities/organizations/repos/repo.js +156 -0
  201. package/src/entities/organizations/repos/search-by-aggregation-extension.js +128 -0
  202. package/src/entities/organizations/repos/transform-did-filter.js +13 -0
  203. package/src/entities/organizations/repos/transform-organization-filter.js +106 -0
  204. package/src/entities/registrar-consents/constants.js +10 -0
  205. package/src/entities/registrar-consents/factories/index.js +17 -0
  206. package/src/entities/registrar-consents/factories/registrar-consents-factory.js +38 -0
  207. package/src/entities/registrar-consents/index.js +3 -0
  208. package/src/entities/registrar-consents/repos/registrar-consent-repo-extension.js +55 -0
  209. package/src/entities/registrar-consents/repos/repo.js +31 -0
  210. package/src/entities/signatories/domain/constants.js +12 -0
  211. package/src/entities/signatories/domain/index.js +4 -0
  212. package/src/entities/signatories/domain/organization-emails.js +29 -0
  213. package/src/entities/signatories/factories/index.js +17 -0
  214. package/src/entities/signatories/factories/signatory-status-factory.js +53 -0
  215. package/src/entities/signatories/index.js +5 -0
  216. package/src/entities/signatories/orchestrators/approve-reminder.js +24 -0
  217. package/src/entities/signatories/orchestrators/index.js +6 -0
  218. package/src/entities/signatories/orchestrators/reject-reminder.js +17 -0
  219. package/src/entities/signatories/orchestrators/send-reminders.js +102 -0
  220. package/src/entities/signatories/orchestrators/validate-auth-code.js +56 -0
  221. package/src/entities/signatories/repos/index.js +3 -0
  222. package/src/entities/signatories/repos/repo.js +35 -0
  223. package/src/entities/signatories/repos/signatory-status-state-repo-extension.js +124 -0
  224. package/src/entities/users/domains/constants.js +40 -0
  225. package/src/entities/users/domains/index.js +4 -0
  226. package/src/entities/users/domains/user-registrar-emails.js +52 -0
  227. package/src/entities/users/index.js +4 -0
  228. package/src/entities/users/orchestrators/create-auth0-user.js +60 -0
  229. package/src/entities/users/orchestrators/get-or-create-auth0-user.js +63 -0
  230. package/src/entities/users/orchestrators/index.js +22 -0
  231. package/src/entities/users/orchestrators/user-management.js +157 -0
  232. package/src/fetchers/index.js +19 -0
  233. package/src/fetchers/monitoring/index.js +9 -0
  234. package/src/fetchers/monitoring/monitor-add-to-page-fetcher.js +18 -0
  235. package/src/fetchers/monitoring/monitor-create-fetcher.js +23 -0
  236. package/src/fetchers/monitoring/monitor-delete-fetcher.js +6 -0
  237. package/src/fetchers/monitoring/monitor-get-all-fetcher.js +6 -0
  238. package/src/fetchers/monitoring/section-create-fetcher.js +16 -0
  239. package/src/fetchers/monitoring/section-get-all-fetcher.js +6 -0
  240. package/src/fetchers/monitoring/service-version-fetcher.js +6 -0
  241. package/src/helpers/init-permissions-contract.js +48 -0
  242. package/src/index.js +23 -0
  243. package/src/init-server.js +91 -0
  244. package/src/organizations-registrar-endpoints.js +68 -0
  245. package/src/plugins/authorization.js +233 -0
  246. package/src/plugins/index.js +4 -0
  247. package/src/plugins/pubsub-plugin.js +82 -0
  248. package/src/subscribers/notify-caos.js +63 -0
  249. package/src/subscribers/notify-inviters.js +42 -0
  250. package/src/subscribers/notify-monitoring.js +40 -0
  251. package/src/subscribers/notify-signatory.js +51 -0
  252. package/src/subscribers/notify-support-and-groups.js +95 -0
  253. package/src/templates/invitee-invitation-email-body.hbs +13 -0
  254. package/src/templates/invitee-invitation-email-subject.hbs +1 -0
  255. package/src/templates/signatory-approval-email-body.hbs +92 -0
  256. package/src/templates/support-organization-created-body.hbs +17 -0
  257. package/src/templates/support-organization-created-subject.hbs +1 -0
  258. package/src/templates/support-signatory-max-reminders-reached-email-body.hbs +6 -0
  259. package/src/templates/support-signatory-max-reminders-reached-email-subject.hbs +1 -0
@@ -0,0 +1,32 @@
1
+ const { serviceExists } = require('@verii/did-doc');
2
+ const newError = require('http-errors');
3
+ const { map, find } = require('lodash/fp');
4
+
5
+ const validateServicesForDelete = ({
6
+ didDoc,
7
+ activatedServiceIds,
8
+ servicesIds = [],
9
+ }) =>
10
+ map((serviceId) => {
11
+ if (!serviceExists(didDoc, serviceId)) {
12
+ throw newError(
13
+ 400,
14
+ `Service ${serviceId} was not found in organization ${didDoc.id}`
15
+ );
16
+ }
17
+ if (
18
+ !find(
19
+ (activeServiceId) => activeServiceId === serviceId,
20
+ activatedServiceIds
21
+ )
22
+ ) {
23
+ throw newError(
24
+ 400,
25
+ `Service ${serviceId} was not found in activated services of the organization ${didDoc.id}`
26
+ );
27
+ }
28
+ }, servicesIds);
29
+
30
+ module.exports = {
31
+ validateServicesForDelete,
32
+ };
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ ...require('./adapters'),
3
+ ...require('./domains'),
4
+ ...require('./orchestrators'),
5
+ };
@@ -0,0 +1,106 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ const { resolveDidWeb } = require('@verii/did-web');
18
+ const { omit } = require('lodash/fp');
19
+ const { publish } = require('@spencejs/spence-events');
20
+ const {
21
+ validateByoDidDocService,
22
+ buildOrganizationService,
23
+ validateAdditionalService,
24
+ buildPublicService,
25
+ } = require('../domains');
26
+ const { acceptInvitation } = require('../../invitations');
27
+ const { loadCaoServiceRefs } = require('./load-cao-service-refs');
28
+
29
+ const {
30
+ initAddServiceToOrganization,
31
+ } = require('./init-add-service-to-organization');
32
+
33
+ const initAddService = (fastify) => {
34
+ const addServiceToOrganization = initAddServiceToOrganization(fastify);
35
+
36
+ return async (did, newService, context) => {
37
+ const { repos } = context;
38
+ const organization = await repos.organizations.findOneByDid(did, {
39
+ didDoc: 1,
40
+ profile: 1,
41
+ services: 1,
42
+ ids: 1,
43
+ activatedServiceIds: 1,
44
+ adminEmail: 1,
45
+ didNotCustodied: 1,
46
+ authClients: 1,
47
+ });
48
+
49
+ if (organization.didNotCustodied) {
50
+ const byoDidDocument = await resolveDidWeb(organization.didDoc.id);
51
+
52
+ const organizationKeys = await repos.organizationKeys.find({
53
+ filter: { organizationId: organization._id },
54
+ });
55
+
56
+ validateByoDidDocService(byoDidDocument, newService.id, organizationKeys);
57
+ }
58
+ const invitation = await acceptInvitation(
59
+ newService.invitationCode,
60
+ context
61
+ );
62
+ const newOrganizationService = buildOrganizationService(
63
+ omit(['invitationCode'], newService),
64
+ invitation
65
+ );
66
+
67
+ const caoServiceRefs = await loadCaoServiceRefs(
68
+ [newOrganizationService],
69
+ context
70
+ );
71
+ validateAdditionalService(
72
+ newOrganizationService,
73
+ organization.services,
74
+ caoServiceRefs,
75
+ context
76
+ );
77
+
78
+ const { authClient, createdService, newActivatedServiceIds } =
79
+ await addServiceToOrganization(
80
+ { organization, newService: newOrganizationService, invitation },
81
+ context
82
+ );
83
+
84
+ await publish(
85
+ 'services',
86
+ 'added',
87
+ {
88
+ organization,
89
+ invitation,
90
+ addedServices: [createdService],
91
+ activatedServiceIds: newActivatedServiceIds,
92
+ caoServiceRefs,
93
+ },
94
+ context
95
+ );
96
+
97
+ return {
98
+ service: buildPublicService(createdService),
99
+ authClient,
100
+ };
101
+ };
102
+ };
103
+
104
+ module.exports = {
105
+ initAddService,
106
+ };
@@ -0,0 +1,142 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ const {
18
+ toRelativeServiceId,
19
+ removeServiceFromDidDoc,
20
+ } = require('@verii/did-doc');
21
+ const { remove, pull, partition, first } = require('lodash/fp');
22
+ const newError = require('http-errors');
23
+ const {
24
+ updateBlockchainPermissionsFromPermittedServices,
25
+ } = require('../adapters');
26
+ const {
27
+ initBuildOrganizationModificationsOnServiceChange,
28
+ } = require('../../organizations/domains');
29
+ const { removeMonitor } = require('../../monitors');
30
+ const { initAuth0Provisioner } = require('../../oauth');
31
+
32
+ const initDeleteService = (fastify) => {
33
+ const { removeAuth0Client } = initAuth0Provisioner(fastify.config);
34
+ const buildOrganizationModificationsOnServiceChange =
35
+ initBuildOrganizationModificationsOnServiceChange(fastify);
36
+
37
+ return async (did, serviceId, context) => {
38
+ const { repos, log, sendError } = context;
39
+
40
+ const organization = await repos.organizations.findOneByDid(did, {
41
+ didDoc: 1,
42
+ services: 1,
43
+ activatedServiceIds: 1,
44
+ authClients: 1,
45
+ didNotCustodied: 1,
46
+ });
47
+
48
+ const relativeServiceId = toRelativeServiceId(serviceId);
49
+ const services = remove({ id: relativeServiceId }, organization.services);
50
+ if (services.length === organization.services.length) {
51
+ throw new newError.NotFound(
52
+ `Service ${relativeServiceId} was not found in organization ${organization.didDoc.id}`
53
+ );
54
+ }
55
+
56
+ let updatedOrganization = await repos.organizations.update(
57
+ organization._id,
58
+ {
59
+ services,
60
+ }
61
+ );
62
+
63
+ if (!organization.didNotCustodied) {
64
+ const { didDoc } = removeServiceFromDidDoc({
65
+ didDoc: organization.didDoc,
66
+ serviceId: relativeServiceId,
67
+ });
68
+ updatedOrganization = await repos.organizations.update(organization._id, {
69
+ didDoc,
70
+ });
71
+ }
72
+
73
+ // Update Profile
74
+ const activatedServiceIds = pull(
75
+ relativeServiceId,
76
+ organization.activatedServiceIds
77
+ );
78
+
79
+ const organizationModifications =
80
+ await buildOrganizationModificationsOnServiceChange({
81
+ organization: updatedOrganization,
82
+ activatedServiceIds,
83
+ });
84
+
85
+ const updatedOrganizationWithRemovedService =
86
+ await repos.organizations.update(
87
+ organization._id,
88
+ organizationModifications
89
+ );
90
+
91
+ await updateBlockchainPermissionsFromPermittedServices(
92
+ {
93
+ organization: updatedOrganizationWithRemovedService,
94
+ },
95
+ context
96
+ );
97
+
98
+ // Update Auth0
99
+ log.info(
100
+ {
101
+ relativeServiceId,
102
+ authClients: organization.authClients,
103
+ oldServices: organization.services,
104
+ newServices: updatedOrganization.services,
105
+ },
106
+ 'Updating "authClients"'
107
+ );
108
+ const [authClientsToDelete, remainingAuthClients] = partition(
109
+ { serviceId: relativeServiceId },
110
+ organization.authClients
111
+ );
112
+
113
+ try {
114
+ log.info({ authClientsToDelete }, 'Removing authClient');
115
+ await removeAuth0Client(first(authClientsToDelete));
116
+ await repos.organizations.update(organization._id, {
117
+ authClients: remainingAuthClients,
118
+ });
119
+ } catch (error) {
120
+ const message = 'Error Provisioning Auth0 Apps';
121
+ const messageContext = { authClientsToDelete };
122
+ log.error({ err: error, ...messageContext }, message);
123
+ sendError(error, messageContext);
124
+ }
125
+
126
+ try {
127
+ await removeMonitor(
128
+ {
129
+ orgId: organization.didDoc.id,
130
+ serviceId: relativeServiceId,
131
+ },
132
+ context
133
+ );
134
+ } catch (error) {
135
+ const message = 'Failed to remove organization service monitor';
136
+ log.error({ err: error }, message);
137
+ sendError(error, { message });
138
+ }
139
+ };
140
+ };
141
+
142
+ module.exports = { initDeleteService };
@@ -0,0 +1,36 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ const { find } = require('lodash/fp');
18
+ const newError = require('http-errors');
19
+ const {
20
+ buildPublicService,
21
+ OrganizationServiceErrorMessages,
22
+ } = require('../domains');
23
+
24
+ const getService = async (did, serviceId, context) => {
25
+ const { repos } = context;
26
+ const organization = await repos.organizations.findOneByDid(did);
27
+ const service = find({ id: `#${serviceId}` }, organization.services);
28
+ if (service == null) {
29
+ throw newError.NotFound(
30
+ OrganizationServiceErrorMessages.ORGANIZATION_SERVICE_NOT_FOUND
31
+ );
32
+ }
33
+ return buildPublicService(service);
34
+ };
35
+
36
+ module.exports = { getService };
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ ...require('./add-service'),
3
+ ...require('./delete-service'),
4
+ ...require('./get-service'),
5
+ ...require('./init-add-service-to-organization'),
6
+ ...require('./load-cao-service-refs'),
7
+ ...require('./update-service'),
8
+ };
@@ -0,0 +1,141 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ const { addServiceToDidDoc } = require('@verii/did-doc');
19
+ const { concat, first, isEmpty } = require('lodash/fp');
20
+ const { createStakesAccount } = require('@verii/fineract-client');
21
+ const { initAuth0Provisioner } = require('../../oauth');
22
+ const {
23
+ initBuildOrganizationModificationsOnServiceChange,
24
+ } = require('../../organizations/domains');
25
+ const {
26
+ initProvisionAuth0Clients,
27
+ updateBlockchainPermissionsFromPermittedServices,
28
+ } = require('../adapters');
29
+ const {
30
+ activateServices,
31
+ isNewNodeOperatorService,
32
+ getServiceConsentType,
33
+ } = require('../domains');
34
+
35
+ const initAddServiceToOrganization = (fastify) => {
36
+ const auth0Provisioner = initAuth0Provisioner(fastify.config);
37
+ const provisionAuth0Clients = initProvisionAuth0Clients(auth0Provisioner);
38
+
39
+ const buildOrganizationModificationsOnServiceChange =
40
+ initBuildOrganizationModificationsOnServiceChange(fastify);
41
+
42
+ return async ({ organization, newService }, context) => {
43
+ const { repos, user, config } = context;
44
+
45
+ const createdService = await repos.organizations.addService(
46
+ organization._id,
47
+ newService
48
+ );
49
+
50
+ if (!organization.didNotCustodied) {
51
+ const { didDoc } = addServiceToDidDoc({
52
+ didDoc: organization.didDoc,
53
+ service: newService,
54
+ });
55
+
56
+ await repos.organizations.update(organization._id, { didDoc });
57
+ }
58
+
59
+ // add consent
60
+ await repos.registrarConsents.registerConsent({
61
+ userId: user.sub,
62
+ organizationId: organization._id,
63
+ type: getServiceConsentType(createdService),
64
+ version: config.serviceConsentVersion,
65
+ serviceId: createdService.id,
66
+ });
67
+
68
+ // add stakes account
69
+ if (isNewNodeOperatorService(organization, createdService)) {
70
+ const stakesAccountId = await createStakesAccount(
71
+ organization.ids.fineractClientId,
72
+ organization.didDoc.id,
73
+ context
74
+ );
75
+
76
+ await context.repos.organizations.update(organization._id, {
77
+ ids: { ...organization.ids, stakesAccountId },
78
+ });
79
+ }
80
+
81
+ // Get activated services ids
82
+ const newActivatedServiceIds = activateServices(
83
+ organization.didDoc.id,
84
+ [createdService],
85
+ context
86
+ );
87
+
88
+ const createdAuthClients = await provisionAuth0Clients(
89
+ organization,
90
+ [createdService],
91
+ newActivatedServiceIds,
92
+ context
93
+ );
94
+
95
+ const organizationModifications =
96
+ await buildOrganizationModificationsOnServiceChange({
97
+ organization,
98
+ services: concat(organization.services, [createdService]),
99
+ activatedServiceIds: concat(
100
+ organization.activatedServiceIds ?? [],
101
+ newActivatedServiceIds
102
+ ),
103
+ authClients: concat(organization.authClients ?? [], createdAuthClients),
104
+ });
105
+
106
+ const activatedOrganization = await context.repos.organizations.update(
107
+ organization._id,
108
+ organizationModifications,
109
+ {
110
+ _id: 1,
111
+ didDoc: 1,
112
+ profile: 1,
113
+ services: 1,
114
+ activatedServiceIds: 1,
115
+ verifiableCredentialJwt: 1,
116
+ adminEmail: 1,
117
+ ids: 1,
118
+ authClients: 1,
119
+ }
120
+ );
121
+
122
+ if (!isEmpty(newActivatedServiceIds)) {
123
+ await updateBlockchainPermissionsFromPermittedServices(
124
+ {
125
+ organization: activatedOrganization,
126
+ },
127
+ context
128
+ );
129
+ }
130
+
131
+ return {
132
+ authClient: first(createdAuthClients),
133
+ createdService,
134
+ newActivatedServiceIds,
135
+ };
136
+ };
137
+ };
138
+
139
+ module.exports = {
140
+ initAddServiceToOrganization,
141
+ };
@@ -0,0 +1,56 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ const { isEmpty, flow, includes, map, find, fromPairs } = require('lodash/fp');
19
+ const { splitDidUrlWithFragment } = require('@verii/did-doc');
20
+ const { extractCaoServiceRefs } = require('../domains');
21
+
22
+ const loadCaoServiceRefs = async (services, { repos }) => {
23
+ const caoServiceIds = extractCaoServiceRefs(services);
24
+ const caoOrganizations = await repos.organizations.findCaos(caoServiceIds);
25
+ return buildReferenceCaoServices({
26
+ caoServiceIds,
27
+ caoOrganizations,
28
+ });
29
+ };
30
+
31
+ const buildReferenceCaoServices = ({ caoServiceIds, caoOrganizations }) => {
32
+ if (isEmpty(caoOrganizations) || isEmpty(caoServiceIds)) {
33
+ return {};
34
+ }
35
+ return flow(
36
+ map((caoServiceId) => {
37
+ const [caoDid, serviceFragment] = splitDidUrlWithFragment(caoServiceId);
38
+ const caoOrganization = find((org) => {
39
+ return (
40
+ org.didDoc.id === caoDid || includes(org.didDoc.alsoKnownAs, caoDid)
41
+ );
42
+ }, caoOrganizations);
43
+ const caoService = find(
44
+ { id: serviceFragment },
45
+ caoOrganization?.services
46
+ );
47
+ return [caoServiceId, { caoOrganization, caoService }];
48
+ }),
49
+ fromPairs
50
+ )(caoServiceIds);
51
+ };
52
+
53
+ module.exports = {
54
+ loadCaoServiceRefs,
55
+ buildReferenceCaoServices,
56
+ };
@@ -0,0 +1,103 @@
1
+ /*
2
+ * Copyright 2025 Velocity Team
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+ const { isEmpty, find } = require('lodash/fp');
18
+ const newError = require('http-errors');
19
+ const { resolveDidWeb } = require('@verii/did-web');
20
+ const {
21
+ serviceExists,
22
+ toRelativeServiceId,
23
+ updateServicesOnDidDoc,
24
+ } = require('@verii/did-doc');
25
+ const {
26
+ buildPublicService,
27
+ OrganizationServiceErrorMessages,
28
+ buildOrganizationServiceForUpdate,
29
+ validateService,
30
+ } = require('../domains');
31
+ const { loadCaoServiceRefs } = require('./load-cao-service-refs');
32
+
33
+ const updateService = async (did, serviceId, replacementService, context) => {
34
+ const { repos } = context;
35
+ const organization = await repos.organizations.findOneByDid(did);
36
+
37
+ // TODO remove and replace with schema update
38
+ if (!isEmpty(replacementService.id)) {
39
+ throw newError.BadRequest(
40
+ OrganizationServiceErrorMessages.SERVICE_ID_CANNOT_BE_UPDATED
41
+ );
42
+ }
43
+ if (!isEmpty(replacementService.type)) {
44
+ throw newError.BadRequest(
45
+ OrganizationServiceErrorMessages.SERVICE_TYPE_CANNOT_BE_UPDATED
46
+ );
47
+ }
48
+
49
+ const service = await updateOrganizationService(
50
+ {
51
+ organization,
52
+ serviceId: `#${serviceId}`,
53
+ updates: replacementService,
54
+ },
55
+ context
56
+ );
57
+ return buildPublicService(service);
58
+ };
59
+
60
+ const updateOrganizationService = async (
61
+ { organization, serviceId, updates },
62
+ context
63
+ ) => {
64
+ const { repos } = context;
65
+ const didDocument = organization.didNotCustodied
66
+ ? await resolveDidWeb(organization.didDoc.id)
67
+ : organization.didDoc;
68
+
69
+ // load and verify existing services from db and did document
70
+ const existingDidDocService = serviceExists(didDocument, serviceId);
71
+ const existingDbService = find(
72
+ { id: toRelativeServiceId(serviceId) },
73
+ organization.services
74
+ );
75
+ if (isEmpty(existingDidDocService) || isEmpty(existingDbService)) {
76
+ throw new newError.NotFound(
77
+ `Service ${serviceId} was not found in organization ${organization.didDoc.id}`
78
+ );
79
+ }
80
+
81
+ const caoServiceRefs = await loadCaoServiceRefs([updates], context);
82
+
83
+ const service = buildOrganizationServiceForUpdate(updates, existingDbService);
84
+ validateService(service, caoServiceRefs, context);
85
+
86
+ if (!organization.didNotCustodied) {
87
+ await updateDidDoc(organization, service, context);
88
+ }
89
+
90
+ return repos.organizations.updateService(organization._id, service);
91
+ };
92
+
93
+ const updateDidDoc = async (organization, service, context) => {
94
+ const { repos } = context;
95
+ const { didDoc } = updateServicesOnDidDoc({
96
+ didDoc: organization.didDoc,
97
+ services: [service],
98
+ });
99
+
100
+ await repos.organizations.update(organization._id, { didDoc });
101
+ };
102
+
103
+ module.exports = { updateService };
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ ...require('./init-organization-registrar-emails'),
3
+ ...require('./init-send-activation-emails-to-caos'),
4
+ ...require('./send-email-invitation-accepted-to-inviter'),
5
+ ...require('./send-email-notifications'),
6
+ };