@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,617 @@
1
+ const {
2
+ all,
3
+ concat,
4
+ difference,
5
+ filter,
6
+ first,
7
+ flow,
8
+ isEmpty,
9
+ map,
10
+ partition,
11
+ pullAll,
12
+ some,
13
+ uniq,
14
+ forEach,
15
+ } = require('lodash/fp');
16
+ const newError = require('http-errors');
17
+ const {
18
+ buildDidDocWithAlternativeId,
19
+ toRelativeServiceId,
20
+ } = require('@verii/did-doc');
21
+ const { resolveDidWeb } = require('@verii/did-web');
22
+ const {
23
+ VerifiableCredentialTypes,
24
+ VerifiableCredentialFormats,
25
+ } = require('@verii/verifiable-credentials');
26
+ const { decodeCredentialJwt, jwkFromSecp256k1Key } = require('@verii/jwt');
27
+ const { publish } = require('@spencejs/spence-events');
28
+ const {
29
+ verifyUserOrganizationReadAuthorized,
30
+ } = require('../../../plugins/authorization');
31
+ const {
32
+ initBuildOrganizationModificationsOnServiceChange,
33
+ runAllOrgChecks,
34
+ OrganizationErrorMessages,
35
+ OrganizationServiceErrorMessages,
36
+ RegistrarScopes,
37
+ initProvisionAuth0ClientGrants,
38
+ loadCaoServiceRefs,
39
+ updateBlockchainPermissionsFromPermittedServices,
40
+ buildPublicProfile,
41
+ validateServicesForDelete,
42
+ initAuth0Provisioner,
43
+ validateByoDidDocService,
44
+ } = require('../../../entities');
45
+
46
+ const organizationController = async (fastify) => {
47
+ const { sendError } = fastify;
48
+
49
+ const auth0Provisioner = initAuth0Provisioner(fastify.config);
50
+ const provisionAuth0ClientGrants =
51
+ initProvisionAuth0ClientGrants(auth0Provisioner);
52
+
53
+ const buildOrganizationModificationsOnServiceChange =
54
+ initBuildOrganizationModificationsOnServiceChange(fastify);
55
+
56
+ fastify
57
+ .get(
58
+ '/',
59
+ {
60
+ onRequest: fastify.verifyAccessToken([
61
+ RegistrarScopes.ReadOrganizations,
62
+ RegistrarScopes.AdminOrganizations,
63
+ ]),
64
+ preHandler: [verifyUserOrganizationReadAuthorized],
65
+ schema: fastify.autoSchema({
66
+ security: [
67
+ {
68
+ RegistrarOAuth2: [
69
+ RegistrarScopes.ReadOrganizations,
70
+ RegistrarScopes.AdminOrganizations,
71
+ ],
72
+ },
73
+ ],
74
+ response: {
75
+ 200: {
76
+ $ref: 'did-doc#',
77
+ },
78
+ },
79
+ }),
80
+ },
81
+ async ({ repos, params }) => {
82
+ const organization = await repos.organizations.findOne({
83
+ filter: {
84
+ 'didDoc.id': params.did,
85
+ didNotCustodied: false,
86
+ },
87
+ });
88
+ if (organization == null) {
89
+ throw newError.NotFound(
90
+ OrganizationErrorMessages.ORGANIZATION_NOT_FOUND
91
+ );
92
+ }
93
+ return organization.didDoc;
94
+ }
95
+ )
96
+ .get(
97
+ '/resolve-vc',
98
+ {
99
+ schema: fastify.autoSchema({
100
+ query: {
101
+ type: 'object',
102
+ properties: {
103
+ type: {
104
+ description: 'The type of verifiable credential to retrieve',
105
+ type: 'string',
106
+ },
107
+ },
108
+ required: ['type'],
109
+ },
110
+ response: {
111
+ 200: {
112
+ type: 'array',
113
+ items: { $ref: 'organization-profile-verifiable-credential#' },
114
+ },
115
+ ...fastify.NotFoundResponse,
116
+ },
117
+ }),
118
+ },
119
+ async ({ repos, params, query }) => {
120
+ const orgDoc = await repos.organizations.findOneByDid(params.did, {
121
+ signedProfileVcJwt: 1,
122
+ id: -1,
123
+ });
124
+
125
+ if (isEmpty(orgDoc)) {
126
+ throw newError.NotFound(
127
+ OrganizationErrorMessages.ORGANIZATION_NOT_FOUND
128
+ );
129
+ }
130
+ if (query.type !== VerifiableCredentialTypes.BASIC_PROFILE_V1_0) {
131
+ throw newError.BadRequest(
132
+ OrganizationErrorMessages.UNRECOGNIZED_VERIFIABLE_CREDENTIAL_TYPE
133
+ );
134
+ }
135
+ if (orgDoc?.signedProfileVcJwt?.signedCredential == null) {
136
+ return [];
137
+ }
138
+ return [
139
+ {
140
+ format: VerifiableCredentialFormats.JWT_VC,
141
+ vc: orgDoc.signedProfileVcJwt.signedCredential,
142
+ },
143
+ ];
144
+ }
145
+ )
146
+ .get(
147
+ '/resolve-vc/:id',
148
+ {
149
+ schema: fastify.autoSchema({
150
+ params: {
151
+ type: 'object',
152
+ properties: {
153
+ id: {
154
+ type: 'string',
155
+ },
156
+ },
157
+ },
158
+ response: {
159
+ 200: { $ref: 'organization-profile-verifiable-credential#' },
160
+ },
161
+ }),
162
+ },
163
+ async ({ repos, params }) => {
164
+ const orgDoc = await repos.organizations.findOneByDid(params.did, {
165
+ signedProfileVcJwt: 1,
166
+ id: -1,
167
+ });
168
+
169
+ if (isEmpty(orgDoc)) {
170
+ throw newError.NotFound(
171
+ OrganizationErrorMessages.ORGANIZATION_NOT_FOUND
172
+ );
173
+ }
174
+
175
+ const { credentialId, signedCredential } = orgDoc.signedProfileVcJwt;
176
+
177
+ if (credentialId !== params.id) {
178
+ throw newError.NotFound(
179
+ OrganizationErrorMessages.VERIFIABLE_CREDENTIAL_NOT_FOUND
180
+ );
181
+ }
182
+ return {
183
+ format: VerifiableCredentialFormats.JWT_VC,
184
+ vc: signedCredential,
185
+ };
186
+ }
187
+ )
188
+ .get(
189
+ '/verified-profile',
190
+ {
191
+ schema: fastify.autoSchema({
192
+ response: {
193
+ 200: { $ref: 'organization-verified-profile#' },
194
+ },
195
+ }),
196
+ },
197
+ async (req) => {
198
+ const { repos, params, config } = req;
199
+ const org = await repos.organizations.findOneByDid(params.did, {
200
+ didDoc: 1,
201
+ signedProfileVcJwt: 1,
202
+ _id: -1,
203
+ });
204
+
205
+ const {
206
+ signedProfileVcJwt: { signedCredential },
207
+ } = org;
208
+ const credentialChecks = await runAllOrgChecks(
209
+ {
210
+ signedCredential,
211
+ rootDid: config.rootDid,
212
+ rootJwk: jwkFromSecp256k1Key(config.rootPrivateKey, false),
213
+ },
214
+ req
215
+ );
216
+
217
+ const decodedCredential = await decodeCredentialJwt(signedCredential);
218
+ const didDoc = buildDidDocWithAlternativeId(params.did, org.didDoc);
219
+ const profile = {
220
+ ...decodedCredential.credentialSubject,
221
+ id: didDoc.id,
222
+ alsoKnownAs: didDoc.alsoKnownAs,
223
+ };
224
+ return {
225
+ ...decodedCredential,
226
+ credentialChecks,
227
+ credentialSubject: buildPublicProfile(profile),
228
+ };
229
+ }
230
+ )
231
+ .post(
232
+ '/deactivate-services',
233
+ {
234
+ onRequest: fastify.verifyAccessToken([
235
+ RegistrarScopes.AdminOrganizations,
236
+ ]),
237
+ schema: fastify.autoSchema({
238
+ security: [
239
+ {
240
+ RegistrarOAuth2: [RegistrarScopes.AdminOrganizations],
241
+ },
242
+ ],
243
+ body: {
244
+ type: 'object',
245
+ properties: {
246
+ serviceIds: {
247
+ type: 'array',
248
+ minItems: 1,
249
+ items: { type: 'string' },
250
+ },
251
+ },
252
+ required: ['serviceIds'],
253
+ },
254
+ response: {
255
+ 200: {
256
+ type: 'object',
257
+ properties: {
258
+ profile: {
259
+ $ref: 'organization-profile#',
260
+ },
261
+ activatedServiceIds: {
262
+ type: 'array',
263
+ items: { type: 'string' },
264
+ },
265
+ updatedAt: {
266
+ type: 'string',
267
+ format: 'date-time',
268
+ },
269
+ createdAt: {
270
+ type: 'string',
271
+ format: 'date-time',
272
+ },
273
+ },
274
+ },
275
+ },
276
+ }),
277
+ },
278
+ async (req) => {
279
+ const {
280
+ repos,
281
+ params,
282
+ body: { serviceIds: bodyServicesIds },
283
+ log,
284
+ } = req;
285
+ const servicesIds = flow(
286
+ map(toRelativeServiceId),
287
+ uniq
288
+ )(bodyServicesIds ?? []);
289
+
290
+ const organization = await repos.organizations.findOneByDid(
291
+ params.did,
292
+ {
293
+ didDoc: 1,
294
+ authClients: 1,
295
+ activatedServiceIds: 1,
296
+ profile: 1,
297
+ didNotCustodied: 1,
298
+ services: 1,
299
+ }
300
+ );
301
+
302
+ if (organization == null) {
303
+ throw newError.NotFound(
304
+ OrganizationErrorMessages.ORGANIZATION_NOT_FOUND
305
+ );
306
+ }
307
+
308
+ const didDocument = organization.didNotCustodied
309
+ ? await resolveDidWeb(organization.didDoc.id)
310
+ : organization.didDoc;
311
+
312
+ validateServicesForDelete({
313
+ didDoc: didDocument,
314
+ servicesIds,
315
+ activatedServiceIds: organization.activatedServiceIds,
316
+ });
317
+
318
+ const activatedServiceIds = pullAll(
319
+ servicesIds,
320
+ organization.activatedServiceIds
321
+ );
322
+
323
+ const organizationModifications =
324
+ await buildOrganizationModificationsOnServiceChange({
325
+ organization,
326
+ activatedServiceIds,
327
+ });
328
+
329
+ const updatedOrganization = await repos.organizations.update(
330
+ organization._id,
331
+ organizationModifications
332
+ );
333
+
334
+ await updateBlockchainPermissionsFromPermittedServices(
335
+ {
336
+ organization: updatedOrganization,
337
+ },
338
+ req
339
+ );
340
+
341
+ const removeGrant = async (serviceId) => {
342
+ const org = await repos.organizations.findOneByDid(params.did, {
343
+ didDoc: 1,
344
+ authClients: 1,
345
+ activatedServiceIds: 1,
346
+ profile: 1,
347
+ });
348
+ const [authClientsToDelete, remainingAuthClients] = partition(
349
+ { serviceId: toRelativeServiceId(serviceId) },
350
+ org.authClients
351
+ );
352
+ const authClientToDelete = first(authClientsToDelete);
353
+ try {
354
+ await auth0Provisioner.removeAuth0Grants(authClientToDelete);
355
+ await repos.organizations.update(org._id, {
356
+ authClients: [
357
+ { ...authClientToDelete, clientGrantIds: [] },
358
+ ...remainingAuthClients,
359
+ ],
360
+ });
361
+ } catch (error) {
362
+ const message = 'Error Provisioning Auth0 Apps';
363
+ const messageContext = { authClientToDelete };
364
+ log.error({ err: error, ...messageContext }, message);
365
+ sendError(error, messageContext);
366
+ }
367
+ };
368
+
369
+ for (const serviceId of servicesIds) {
370
+ // eslint-disable-next-line no-await-in-loop
371
+ await removeGrant(serviceId);
372
+ }
373
+
374
+ const updatedOrg = await repos.organizations.findOneByDid(params.did, {
375
+ activatedServiceIds: 1,
376
+ profile: 1,
377
+ createdAt: 1,
378
+ updatedAt: 1,
379
+ });
380
+ return {
381
+ profile: {
382
+ id: params.did,
383
+ ...updatedOrg.profile,
384
+ },
385
+ activatedServiceIds: updatedOrg.activatedServiceIds,
386
+ createdAt: updatedOrg.createdAt,
387
+ updatedAt: updatedOrg.updatedAt,
388
+ };
389
+ }
390
+ )
391
+ .post(
392
+ '/activate-services',
393
+ {
394
+ onRequest: fastify.verifyAccessToken([
395
+ RegistrarScopes.AdminOrganizations,
396
+ ]),
397
+ schema: fastify.autoSchema({
398
+ security: [
399
+ {
400
+ RegistrarOAuth2: [RegistrarScopes.AdminOrganizations],
401
+ },
402
+ ],
403
+ body: {
404
+ type: 'object',
405
+ properties: {
406
+ serviceIds: {
407
+ type: 'array',
408
+ items: {
409
+ type: 'string',
410
+ },
411
+ minItems: 1,
412
+ },
413
+ },
414
+ required: ['serviceIds'],
415
+ },
416
+ response: {
417
+ 200: {
418
+ type: 'object',
419
+ properties: {
420
+ profile: { $ref: 'organization-profile#' },
421
+ activatedServiceIds: {
422
+ type: 'array',
423
+ items: {
424
+ type: 'string',
425
+ },
426
+ },
427
+ updatedAt: {
428
+ type: 'string',
429
+ format: 'date-time',
430
+ },
431
+ createdAt: {
432
+ type: 'string',
433
+ format: 'date-time',
434
+ },
435
+ },
436
+ },
437
+ },
438
+ }),
439
+ },
440
+ async (req) => {
441
+ const {
442
+ repos,
443
+ params,
444
+ body: { serviceIds },
445
+ log,
446
+ } = req;
447
+ const organization = await repos.organizations.findOneByDid(
448
+ params.did,
449
+ {
450
+ _id: 1,
451
+ didDoc: 1,
452
+ profile: 1,
453
+ activatedServiceIds: 1,
454
+ verifiableCredentialJwt: 1,
455
+ adminEmail: 1,
456
+ ids: 1,
457
+ didNotCustodied: 1,
458
+ authClients: 1,
459
+ services: 1,
460
+ updatedAt: 1,
461
+ createdAt: 1,
462
+ }
463
+ );
464
+
465
+ const serviceIdsToActivate = difference(
466
+ serviceIds,
467
+ organization.activatedServiceIds
468
+ );
469
+ if (isEmpty(serviceIdsToActivate)) {
470
+ return {};
471
+ }
472
+
473
+ if (
474
+ !all(
475
+ (id) => some({ id }, organization.services),
476
+ serviceIdsToActivate
477
+ )
478
+ ) {
479
+ throw newError.BadRequest(
480
+ OrganizationServiceErrorMessages.ORGANIZATION_SERVICE_NOT_FOUND
481
+ );
482
+ }
483
+
484
+ // validate byo did scenarios
485
+ if (organization.didNotCustodied) {
486
+ const didDocument = await resolveDidWeb(organization.didDoc.id);
487
+ const keys = await repos.organizationKeys.find({
488
+ filter: { organizationId: organization._id },
489
+ });
490
+
491
+ forEach((serviceId) => {
492
+ validateByoDidDocService(didDocument, serviceId, keys);
493
+ }, serviceIdsToActivate);
494
+ }
495
+
496
+ // Update Profile
497
+ const activatedServiceIds = flow(
498
+ concat(organization.activatedServiceIds ?? []),
499
+ uniq
500
+ )(serviceIdsToActivate);
501
+
502
+ const authClients = await provisionAuth0ClientGrants(
503
+ organization,
504
+ activatedServiceIds
505
+ );
506
+
507
+ const organizationModifications =
508
+ await buildOrganizationModificationsOnServiceChange({
509
+ organization,
510
+ activatedServiceIds,
511
+ authClients,
512
+ });
513
+
514
+ const updatedOrganization = await repos.organizations.update(
515
+ organization._id,
516
+ organizationModifications
517
+ );
518
+
519
+ await updateBlockchainPermissionsFromPermittedServices(
520
+ {
521
+ organization: updatedOrganization,
522
+ },
523
+ req
524
+ );
525
+
526
+ try {
527
+ const caoServiceRefs = await loadCaoServiceRefs(
528
+ filter(
529
+ (service) => activatedServiceIds.includes(service.id),
530
+ organization.services
531
+ ),
532
+ req
533
+ );
534
+ await publish(
535
+ 'services',
536
+ 'activated',
537
+ {
538
+ organization,
539
+ activatedServiceIds: serviceIdsToActivate,
540
+ caoServiceRefs,
541
+ },
542
+ req
543
+ );
544
+ } catch (error) {
545
+ const message =
546
+ 'Unable to send email notifications after activating services';
547
+ log.error({ err: error }, message);
548
+ sendError(error, { message });
549
+ }
550
+
551
+ return {
552
+ profile: {
553
+ ...updatedOrganization.profile,
554
+ id: params.did,
555
+ verifiableCredentialJwt:
556
+ updatedOrganization.verifiableCredentialJwt,
557
+ },
558
+ activatedServiceIds: organizationModifications.activatedServiceIds,
559
+ createdAt: updatedOrganization.createdAt,
560
+ updatedAt: updatedOrganization.updatedAt,
561
+ };
562
+ }
563
+ )
564
+ .delete(
565
+ '/',
566
+ {
567
+ onRequest: fastify.verifyAccessToken([
568
+ RegistrarScopes.AdminOrganizations,
569
+ ]),
570
+ schema: fastify.autoSchema({
571
+ security: [
572
+ {
573
+ RegistrarOAuth2: [RegistrarScopes.AdminOrganizations],
574
+ },
575
+ ],
576
+ response: {
577
+ 204: { type: 'null' },
578
+ 400: { $ref: 'error#' },
579
+ },
580
+ }),
581
+ },
582
+ async (req, reply) => {
583
+ const { repos, params } = req;
584
+ const orgToDelete = await repos.organizations.findOneByDid(params.did);
585
+
586
+ if (orgToDelete == null) {
587
+ throw newError.NotFound(
588
+ OrganizationErrorMessages.ORGANIZATION_NOT_FOUND
589
+ );
590
+ }
591
+ if (orgToDelete.activatedServiceIds.length > 0) {
592
+ throw newError(400, 'Cant delete. First remove activated services', {
593
+ errorCode: 'deletion_forbidden',
594
+ });
595
+ }
596
+
597
+ const groupsToModify = await repos.groups.find({
598
+ filter: { dids: params.did },
599
+ });
600
+ const groupIds = map('_id', groupsToModify);
601
+ await repos.groups.collection().updateMany(
602
+ { _id: { $in: groupIds } },
603
+ {
604
+ $pull: { dids: orgToDelete.didDoc.id },
605
+ $set: { updatedAt: new Date() },
606
+ }
607
+ );
608
+
609
+ const modifiedProfile = { ...orgToDelete, deletedAt: new Date() };
610
+ repos.organizations.update(orgToDelete._id, modifiedProfile);
611
+
612
+ return reply.status(204).send();
613
+ }
614
+ );
615
+ };
616
+
617
+ module.exports = organizationController;
@@ -0,0 +1,16 @@
1
+ const autohooks = async (fastify) => {
2
+ fastify.autoSchemaPreset({
3
+ params: {
4
+ type: 'object',
5
+ properties: {
6
+ ...fastify.currentAutoSchemaPreset.params.properties,
7
+ invitationId: {
8
+ type: 'string',
9
+ description: 'the invitation id',
10
+ },
11
+ },
12
+ },
13
+ });
14
+ };
15
+
16
+ module.exports = autohooks;