@verii/server-mockvendor 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 (82) hide show
  1. package/.localdev.env +15 -0
  2. package/.standalone.env +5 -0
  3. package/LICENSE +201 -0
  4. package/docker/compose.yml +25 -0
  5. package/jest.config.js +20 -0
  6. package/multilingual-string.schema.json +40 -0
  7. package/package.json +70 -0
  8. package/src/config/config.js +55 -0
  9. package/src/controllers/api/accepted-offers/controller.js +9 -0
  10. package/src/controllers/api/accepted-offers/repo.js +25 -0
  11. package/src/controllers/api/applicants/controller.js +9 -0
  12. package/src/controllers/api/applicants/repo.js +30 -0
  13. package/src/controllers/api/create_did_key/controller.js +29 -0
  14. package/src/controllers/api/create_did_key/schemas/index.js +4 -0
  15. package/src/controllers/api/create_did_key/schemas/jwk-did-request.schema.js +20 -0
  16. package/src/controllers/api/create_did_key/schemas/jwk-did-response.schema.js +41 -0
  17. package/src/controllers/api/create_jwk/controller.js +35 -0
  18. package/src/controllers/api/create_jwk/schemas/index.js +3 -0
  19. package/src/controllers/api/create_jwk/schemas/jwk-response.schema.js +33 -0
  20. package/src/controllers/api/credential-submissions/controller.js +59 -0
  21. package/src/controllers/api/credential-submissions/repo.js +16 -0
  22. package/src/controllers/api/identifications/controller.js +67 -0
  23. package/src/controllers/api/identifications/repo.js +22 -0
  24. package/src/controllers/api/issuing-exchanges/controller.js +218 -0
  25. package/src/controllers/api/issuing-exchanges/fetchers.js +45 -0
  26. package/src/controllers/api/issuing-exchanges/repo.js +27 -0
  27. package/src/controllers/api/jwt/controller.js +69 -0
  28. package/src/controllers/api/jwt/schemas/index.js +6 -0
  29. package/src/controllers/api/jwt/schemas/jwt-request.schema.js +40 -0
  30. package/src/controllers/api/jwt/schemas/jwt-response.schema.js +14 -0
  31. package/src/controllers/api/jwt/schemas/jwt-verify-request.schema.js +17 -0
  32. package/src/controllers/api/jwt/schemas/jwt-verify-response.schema.js +17 -0
  33. package/src/controllers/api/offers/autohooks.js +5 -0
  34. package/src/controllers/api/offers/controller.js +87 -0
  35. package/src/controllers/api/offers/new-mockvendor-offer.schema.js +22 -0
  36. package/src/controllers/api/offers/repo.js +33 -0
  37. package/src/controllers/api/users/controller.js +20 -0
  38. package/src/controllers/api/users/repo.js +29 -0
  39. package/src/controllers/autohooks.js +22 -0
  40. package/src/controllers/inspection/controller.js +39 -0
  41. package/src/controllers/issuing/controller.js +158 -0
  42. package/src/controllers/registrar/controller.js +67 -0
  43. package/src/controllers/registrar/repo.js +24 -0
  44. package/src/controllers/root/controller.js +15 -0
  45. package/src/controllers/schemas/index.js +21 -0
  46. package/src/controllers/schemas/issuer-data.schema.json +26 -0
  47. package/src/entities/index.js +4 -0
  48. package/src/entities/key-pairs/index.js +3 -0
  49. package/src/entities/key-pairs/key-pairs.js +73 -0
  50. package/src/entities/offers/index.js +3 -0
  51. package/src/entities/offers/schemas/generate-offers.schema.js +30 -0
  52. package/src/entities/offers/schemas/index.js +3 -0
  53. package/src/index.js +19 -0
  54. package/src/init-server.js +34 -0
  55. package/src/main.js +18 -0
  56. package/src/standalone.js +8 -0
  57. package/src/start-app-server.js +32 -0
  58. package/test/accepted-offers.test.js +47 -0
  59. package/test/api-users.test.js +170 -0
  60. package/test/create_did_key-controller.test.js +94 -0
  61. package/test/create_jwk-controller.test.js +86 -0
  62. package/test/credential-submissions.test.js +331 -0
  63. package/test/factories/accepted-offers.factory.js +16 -0
  64. package/test/factories/delayed-offer.factory.js +17 -0
  65. package/test/factories/identifications.factory.js +33 -0
  66. package/test/factories/offers.factory.js +64 -0
  67. package/test/factories/users.factory.js +24 -0
  68. package/test/helpers/PastEmploymentPosition-2007-2009-Junior-Project-Manager.json +26 -0
  69. package/test/helpers/PastEmploymentPosition-2009-2015-Project-Manager.json +26 -0
  70. package/test/helpers/helpers/PastEmploymentPosition-2009-2015-Project-Manager.json +26 -0
  71. package/test/helpers/latest-Adam-Smith.json +49 -0
  72. package/test/helpers/legacy-Adam-Smith.json +33 -0
  73. package/test/helpers/mockvendor-build-fastify.js +16 -0
  74. package/test/helpers/tools/verifgen/templates/PastEmploymentPosition-2009-2015-Project-Manager.json +26 -0
  75. package/test/identifications.test.js +56 -0
  76. package/test/issuing-exchanges.test.js +335 -0
  77. package/test/issuing-identify.test.js +137 -0
  78. package/test/jwt-controller.test.js +320 -0
  79. package/test/offers.test.js +682 -0
  80. package/test/registrar.test.js +276 -0
  81. package/test/root.test.js +25 -0
  82. package/test/swagger.test.js +21 -0
@@ -0,0 +1,87 @@
1
+ const { isArray, map } = require('lodash/fp');
2
+ const { nanoid } = require('nanoid');
3
+
4
+ const prepOffer = (offer) => ({
5
+ offerId: nanoid(),
6
+ ...offer,
7
+ });
8
+
9
+ module.exports = async (fastify) => {
10
+ fastify.post(
11
+ '/',
12
+ {
13
+ onRequest: fastify.verifyAdmin,
14
+ schema: {
15
+ body: {
16
+ oneOf: [
17
+ {
18
+ $ref: 'https://velocitycareerlabs.io/new-mockvendor-offer.schema.json#',
19
+ },
20
+ {
21
+ type: 'array',
22
+ items: {
23
+ $ref: 'https://velocitycareerlabs.io/new-mockvendor-offer.schema.json#',
24
+ },
25
+ },
26
+ ],
27
+ },
28
+ },
29
+ },
30
+ async (req) => {
31
+ const { body, repos } = req;
32
+ const offers = isArray(body) ? body : [body];
33
+ const preppedOffers = map(prepOffer, offers);
34
+ return repos.offers.insertMany(preppedOffers);
35
+ }
36
+ );
37
+ fastify.put(
38
+ '/:id',
39
+ {
40
+ onRequest: fastify.verifyAdmin,
41
+ },
42
+ async (req) => {
43
+ const {
44
+ body,
45
+ params: { id },
46
+ repos,
47
+ } = req;
48
+ return repos.offers.update(id, body);
49
+ }
50
+ );
51
+ fastify.get(
52
+ '/:id',
53
+ {
54
+ onRequest: fastify.verifyAdmin,
55
+ },
56
+ async (req) => {
57
+ const {
58
+ params: { id },
59
+ repos,
60
+ } = req;
61
+ return repos.offers.findById(id);
62
+ }
63
+ );
64
+ fastify.get(
65
+ '',
66
+ {
67
+ onRequest: fastify.verifyAdmin,
68
+ },
69
+ async ({ repos }) => {
70
+ const offers = await repos.offers.find({});
71
+ return offers;
72
+ }
73
+ );
74
+ fastify.delete(
75
+ '/:id',
76
+ {
77
+ onRequest: fastify.verifyAdmin,
78
+ },
79
+ async (req) => {
80
+ const {
81
+ params: { id },
82
+ repos,
83
+ } = req;
84
+ return repos.offers.del(id);
85
+ }
86
+ );
87
+ };
@@ -0,0 +1,22 @@
1
+ const {
2
+ newVendorOfferSchema,
3
+ } = require('@verii/server-credentialagent/src/controllers/operator/tenants/_tenantId/offers/schemas');
4
+ const { filter, omit } = require('lodash/fp');
5
+
6
+ module.exports = {
7
+ $schema: 'http://json-schema.org/draft-07/schema#',
8
+ $id: 'https://velocitycareerlabs.io/new-mockvendor-offer.schema.json',
9
+ title: 'new-mockvendor-offer',
10
+ description:
11
+ 'An new mockvendor offer, is the same as a regular new-vendor-offer, but with the issuer specified',
12
+ type: 'object',
13
+ additionalProperties: false,
14
+ properties: {
15
+ ...omit(
16
+ ['offerCreationDate', 'offerExpirationDate'],
17
+ newVendorOfferSchema.properties
18
+ ),
19
+ label: { type: 'string' },
20
+ },
21
+ required: [...filter(['offerId'], newVendorOfferSchema.required), 'issuer'],
22
+ };
@@ -0,0 +1,33 @@
1
+ const {
2
+ autoboxIdsExtension,
3
+ repoFactory,
4
+ } = require('@spencejs/spence-mongo-repos');
5
+
6
+ const repo = (app, opts, next = () => {}) => {
7
+ next();
8
+ return repoFactory(
9
+ {
10
+ name: 'offers',
11
+ entityName: 'offer',
12
+ defaultProjection: {
13
+ _id: 1,
14
+ '@context': 1,
15
+ type: 1,
16
+ issuer: 1,
17
+ credentialSubject: 1,
18
+ linkedCredentials: 1,
19
+ offerId: 1,
20
+ exchangeId: 1,
21
+ replaces: 1,
22
+ relatedResource: 1,
23
+ label: 1,
24
+ createdAt: 1,
25
+ updatedAt: 1,
26
+ },
27
+ extensions: [autoboxIdsExtension],
28
+ },
29
+ app
30
+ );
31
+ };
32
+
33
+ module.exports = repo;
@@ -0,0 +1,20 @@
1
+ const { map, toLower } = require('lodash/fp');
2
+
3
+ const userController = async (fastify) => {
4
+ fastify.post('/', async ({ body, repos }) =>
5
+ repos.users.insert({ ...body, emails: map(toLower, body.emails) })
6
+ );
7
+ fastify.get('/', async ({ repos }) => repos.users.find({}));
8
+ fastify.get('/:id', async ({ params: { id }, repos }) =>
9
+ repos.users.findById(id)
10
+ );
11
+ fastify.delete('/:id', async ({ params: { id }, repos }) =>
12
+ repos.users.del(id)
13
+ );
14
+
15
+ fastify.put('/:id', async ({ body, params: { id }, repos }) =>
16
+ repos.users.update(id, body)
17
+ );
18
+ };
19
+
20
+ module.exports = userController;
@@ -0,0 +1,29 @@
1
+ const {
2
+ autoboxIdsExtension,
3
+ repoFactory,
4
+ } = require('@spencejs/spence-mongo-repos');
5
+
6
+ module.exports = (app, opts, next = () => {}) => {
7
+ next();
8
+ return repoFactory(
9
+ {
10
+ name: 'users',
11
+ entityName: 'user',
12
+ defaultProjection: {
13
+ _id: 1,
14
+ firstName: 1,
15
+ lastName: 1,
16
+ emails: 1,
17
+ phones: 1,
18
+ address: 1,
19
+ identityCredentials: 1,
20
+ label: 1,
21
+ token: 1,
22
+ createdAt: 1,
23
+ updatedAt: 1,
24
+ },
25
+ extensions: [autoboxIdsExtension],
26
+ },
27
+ app
28
+ );
29
+ };
@@ -0,0 +1,22 @@
1
+ const {
2
+ didServiceSchema,
3
+ modifyDidServiceSchema,
4
+ registrarMessage,
5
+ registrarMessageResponse,
6
+ newOfferRelatedResourceSchema,
7
+ } = require('@verii/common-schemas');
8
+ const {
9
+ newVendorOfferSchema,
10
+ } = require('@verii/server-credentialagent/src/controllers/operator/tenants/_tenantId/offers/schemas');
11
+ const { issuerDataSchema } = require('./schemas');
12
+
13
+ module.exports = async (fastify) => {
14
+ fastify
15
+ .addSchema(issuerDataSchema)
16
+ .addSchema(newOfferRelatedResourceSchema)
17
+ .addSchema(newVendorOfferSchema)
18
+ .addSchema(modifyDidServiceSchema)
19
+ .addSchema(didServiceSchema)
20
+ .addSchema(registrarMessage)
21
+ .addSchema(registrarMessageResponse);
22
+ };
@@ -0,0 +1,39 @@
1
+ const { map, omit } = require('lodash/fp');
2
+
3
+ const prepCreds = (body) => {
4
+ const metadata = omit(['credentials'], body);
5
+ return map((c) => ({ ...c, ...metadata }), body.credentials);
6
+ };
7
+
8
+ module.exports = async (fastify) => {
9
+ fastify.post('/find-or-create-applicant', async (request) => {
10
+ const { body, repos } = request;
11
+ const applicant = await repos.applicants.insert(body);
12
+ return { vendorApplicantId: applicant._id };
13
+ });
14
+
15
+ fastify.post('/add-credentials-to-applicant', async (request) => {
16
+ const { body, repos } = request;
17
+ await repos.applicants.findById(body.vendorApplicantId);
18
+ const inserted = await repos.credentialSubmissions.insertMany(
19
+ prepCreds(body)
20
+ );
21
+ return { numProcessed: inserted.length };
22
+ });
23
+
24
+ fastify.post('/receive-unchecked-credentials', async (request) => {
25
+ const { body, repos } = request;
26
+ const inserted = await repos.credentialSubmissions.insertMany(
27
+ prepCreds(body)
28
+ );
29
+ return { numProcessed: inserted.length };
30
+ });
31
+
32
+ fastify.post('/receive-checked-credentials', async (request) => {
33
+ const { body, repos } = request;
34
+ const inserted = await repos.credentialSubmissions.insertMany(
35
+ prepCreds(body)
36
+ );
37
+ return { numProcessed: inserted.length };
38
+ });
39
+ };
@@ -0,0 +1,158 @@
1
+ const {
2
+ first,
3
+ isEmpty,
4
+ toLower,
5
+ map,
6
+ omitBy,
7
+ omit,
8
+ isNil,
9
+ } = require('lodash/fp');
10
+ const { wait } = require('@verii/common-functions');
11
+ const newError = require('http-errors');
12
+ const { generateOffersSchema } = require('../../entities');
13
+
14
+ module.exports = async (fastify) => {
15
+ fastify.addSchema(generateOffersSchema(fastify));
16
+
17
+ fastify.post('/identify', async (req) => {
18
+ const { body: identification, repos } = req;
19
+ await repos.identifications.insert({ identification });
20
+ const { emails, vendorOriginContext: token } = identification;
21
+ const user = await repos.users.findOne({
22
+ filter: buildUsersFilter({ emails, token }),
23
+ });
24
+ if (!user) {
25
+ throw new newError.NotFound();
26
+ }
27
+ const vendorUserId = first(user.emails);
28
+ return { vendorUserId };
29
+ });
30
+
31
+ fastify.post(
32
+ '/generate-offers',
33
+ {
34
+ schema: {
35
+ body: {
36
+ type: 'object',
37
+ properties: {
38
+ types: {
39
+ type: 'array',
40
+ items: {
41
+ type: 'string',
42
+ },
43
+ },
44
+ vendorUserId: {
45
+ type: 'string',
46
+ },
47
+ vendorOrganizationId: {
48
+ type: 'string',
49
+ },
50
+ tenantDID: {
51
+ type: 'string',
52
+ },
53
+ exchangeId: {
54
+ type: 'string',
55
+ },
56
+ },
57
+ anyOf: [
58
+ { required: ['vendorOrganizationId'] },
59
+ { required: ['tenantDID'] },
60
+ ],
61
+ },
62
+ response: {
63
+ 200: {
64
+ type: 'object',
65
+ properties: {
66
+ offers: {
67
+ type: 'array',
68
+ items: {
69
+ $ref: 'https://velocitycareerlabs.io/generate-offers.schema.json#',
70
+ },
71
+ },
72
+ },
73
+ },
74
+ },
75
+ },
76
+ },
77
+ async ({ body, repos, config }, reply) => {
78
+ const { omitOfferId, noOffers200, generateOffersDelaySec } = config;
79
+
80
+ await wait(generateOffersDelaySec);
81
+
82
+ const offers = await repos.offers.find(
83
+ { filter: buildOffersFilter(body) },
84
+ omitBy(isNil, {
85
+ _id: 0,
86
+ label: 0,
87
+ createdAt: 0,
88
+ updatedAt: 0,
89
+ offerId: omitOfferId ? 0 : null,
90
+ })
91
+ );
92
+ if (!isEmpty(offers) || noOffers200) {
93
+ return { offers };
94
+ }
95
+
96
+ await repos.issuingExchanges.insert({
97
+ type: body.types,
98
+ ...omit(['types'], body),
99
+ });
100
+
101
+ return reply.status(202).send({});
102
+ }
103
+ );
104
+
105
+ fastify.post('/receive-issued-credentials', async (req) => {
106
+ const { body, repos } = req;
107
+ return repos.acceptedOffers.insert(body);
108
+ });
109
+ };
110
+
111
+ const buildIssuerFilter = ({ tenantDID, vendorOrganizationId }) => {
112
+ if (!isEmpty(tenantDID) && !isEmpty(vendorOrganizationId)) {
113
+ return {
114
+ $or: [
115
+ { 'issuer.id': tenantDID },
116
+ { 'issuer.vendorOrganizationId': vendorOrganizationId },
117
+ ],
118
+ };
119
+ }
120
+ if (!isEmpty(tenantDID)) {
121
+ return { 'issuer.id': tenantDID };
122
+ }
123
+ if (!isEmpty(vendorOrganizationId)) {
124
+ return { 'issuer.vendorOrganizationId': vendorOrganizationId };
125
+ }
126
+ return {};
127
+ };
128
+ const buildTypesFilter = ({ types }) => {
129
+ if (!isEmpty(types)) {
130
+ return { type: { $elemMatch: { $in: types } } };
131
+ }
132
+
133
+ return {};
134
+ };
135
+
136
+ const buildUsersFilter = ({ emails, token }) => {
137
+ const $or = [];
138
+ if (!isEmpty(emails)) {
139
+ $or.push({
140
+ emails: { $in: map(toLower, emails) },
141
+ });
142
+ }
143
+ if (!isEmpty(token)) {
144
+ $or.push({
145
+ token,
146
+ });
147
+ }
148
+ return {
149
+ $or,
150
+ };
151
+ };
152
+
153
+ const buildOffersFilter = ({ vendorUserId, ...props }) => ({
154
+ 'credentialSubject.vendorUserId': vendorUserId,
155
+ exchangeId: { $exists: false },
156
+ ...buildIssuerFilter(props),
157
+ ...buildTypesFilter(props),
158
+ });
@@ -0,0 +1,67 @@
1
+ const { wait } = require('@verii/common-functions');
2
+ const { verifyVnfSignature } = require('@verii/crypto');
3
+ const { VNF_SIGNATURE_HTTP_HEADER_NAME } = require('@verii/crypto');
4
+
5
+ module.exports = async (fastify) => {
6
+ fastify.post(
7
+ '/registrar-webhook',
8
+ {
9
+ schema: {
10
+ body: { $ref: 'registrar-message#' },
11
+ response: {
12
+ 200: { $ref: 'registrar-message-response#' },
13
+ },
14
+ },
15
+ },
16
+ async (req) => {
17
+ await processingRequest(req);
18
+ return { messageType: 'ack', messageId: req.body.messageId };
19
+ }
20
+ );
21
+ fastify.post(
22
+ '/registrar-webhook-delay',
23
+ {
24
+ schema: {
25
+ body: { $ref: 'registrar-message#' },
26
+ response: {
27
+ 200: { $ref: 'registrar-message-response#' },
28
+ },
29
+ },
30
+ },
31
+ async (req) => {
32
+ await wait(30000);
33
+ await processingRequest(req);
34
+ return { messageType: 'ack', messageId: req.body.messageId };
35
+ }
36
+ );
37
+ fastify.post(
38
+ '/registrar-webhook-bad-protocol',
39
+ {
40
+ schema: {
41
+ body: { $ref: 'registrar-message#' },
42
+ response: {
43
+ 200: {
44
+ type: 'object',
45
+ properties: {
46
+ foo: { type: 'string' },
47
+ },
48
+ },
49
+ },
50
+ },
51
+ },
52
+ async (req) => {
53
+ await processingRequest(req);
54
+ return { foo: 'foo' };
55
+ }
56
+ );
57
+ };
58
+
59
+ const processingRequest = async (req) => {
60
+ const { repos } = req;
61
+ const vnfSignatureVerified = verifyVnfSignature(
62
+ req.body,
63
+ req.headers[VNF_SIGNATURE_HTTP_HEADER_NAME],
64
+ req
65
+ );
66
+ await repos.messages.insert({ ...req.body, vnfSignatureVerified });
67
+ };
@@ -0,0 +1,24 @@
1
+ const {
2
+ autoboxIdsExtension,
3
+ repoFactory,
4
+ } = require('@spencejs/spence-mongo-repos');
5
+
6
+ module.exports = (app, opts, next = () => {}) => {
7
+ next();
8
+ return repoFactory(
9
+ {
10
+ name: 'messages',
11
+ entityName: 'message',
12
+ defaultProjection: {
13
+ _id: 1,
14
+ messageType: 1,
15
+ messageId: 1,
16
+ payload: 1,
17
+ createdAt: 1,
18
+ updatedAt: 1,
19
+ },
20
+ extensions: [autoboxIdsExtension],
21
+ },
22
+ app
23
+ );
24
+ };
@@ -0,0 +1,15 @@
1
+ const rootRoutes = async (fastify) => {
2
+ fastify.get('/', async (req, reply) => {
3
+ reply
4
+ .status(200)
5
+ .send(`Welcome to Mockvendor\nVersion: ${fastify.config.version}\n`);
6
+ });
7
+ fastify.post('/test-integration', async (req, reply) => {
8
+ return reply.status(200).send({ messageReceived: req.body.message });
9
+ });
10
+ };
11
+
12
+ // eslint-disable-next-line better-mutation/no-mutation
13
+ rootRoutes.prefixOverride = '';
14
+
15
+ module.exports = rootRoutes;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Copyright 2023 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 issuerDataSchema = require('./issuer-data.schema.json');
18
+
19
+ module.exports = {
20
+ issuerDataSchema,
21
+ };
@@ -0,0 +1,26 @@
1
+ {
2
+ "title": "issuer-data",
3
+ "type": "object",
4
+ "$id": "https://velocitynetwork.foundation/schemas/issuer-data.schema.json",
5
+ "description": "issuer data schema",
6
+ "properties": {
7
+ "credentialType": {
8
+ "type": "string"
9
+ },
10
+ "issuer": {
11
+ "type": "string"
12
+ },
13
+ "issued": {
14
+ "type": "string",
15
+ "format": "date-time"
16
+ },
17
+ "validFrom": {
18
+ "type": "string",
19
+ "format": "date-time"
20
+ },
21
+ "validUntil": {
22
+ "type": "string",
23
+ "format": "date-time"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ ...require('./key-pairs'),
3
+ ...require('./offers'),
4
+ };
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ ...require('./key-pairs'),
3
+ };
@@ -0,0 +1,73 @@
1
+ const { flow, filter, first, isEmpty, pick, values } = require('lodash/fp');
2
+ const newError = require('http-errors');
3
+
4
+ const keyPairs = {
5
+ secp256k1: {
6
+ id: '9dqEq7bVkmjiw5Wi5oxim',
7
+ // eslint-disable-next-line max-len
8
+ did: 'did:jwk:eyJjcnYiOiJzZWNwMjU2azEiLCJrdHkiOiJFQyIsIngiOiJBWkpreFVRZlNwS3VvNjVaMWlSeWJZallaRUZOQ2N4VzA2TURCOEpjSHdBIiwieSI6Im5uQk5yZ09OeEFkbGFwZ2RSWlpzT1FxQkNZREFieWtnQ2R2b1ZiNWxtVVkifQ',
9
+ // eslint-disable-next-line max-len
10
+ kid: 'did:jwk:eyJjcnYiOiJzZWNwMjU2azEiLCJrdHkiOiJFQyIsIngiOiJBWkpreFVRZlNwS3VvNjVaMWlSeWJZallaRUZOQ2N4VzA2TURCOEpjSHdBIiwieSI6Im5uQk5yZ09OeEFkbGFwZ2RSWlpzT1FxQkNZREFieWtnQ2R2b1ZiNWxtVVkifQ#0',
11
+ alg: 'ES256K',
12
+ publicKey: {
13
+ kty: 'EC',
14
+ x: 'AZJkxUQfSpKuo65Z1iRybYjYZEFNCcxW06MDB8JcHwA',
15
+ y: 'nnBNrgONxAdlapgdRZZsOQqBCYDAbykgCdvoVb5lmUY',
16
+ crv: 'secp256k1',
17
+ },
18
+ privateKey: {
19
+ kty: 'EC',
20
+ x: 'AZJkxUQfSpKuo65Z1iRybYjYZEFNCcxW06MDB8JcHwA',
21
+ y: 'nnBNrgONxAdlapgdRZZsOQqBCYDAbykgCdvoVb5lmUY',
22
+ crv: 'secp256k1',
23
+ d: 'Sn1OGP_FWYqv0EpfjIY-hL9XMp1JI6X3l-M8ovtz3ng',
24
+ },
25
+ },
26
+ 'P-256': {
27
+ id: 'Iv5pwCQfp6e5FsncVgVX0',
28
+ // eslint-disable-next-line max-len
29
+ did: 'did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6IkFYQWxaWThqNGh5cm10dzBoRjNrLTJWT080THZXRzBLNEF5a0JYS25HVWciLCJ5IjoiYzlEVHE5cVRWUTlRQmlsLUgxdGRWN3FZZERic3BhTG5wZ0FJdkRKeEpHayJ9',
30
+ // eslint-disable-next-line max-len
31
+ kid: 'did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6IkFYQWxaWThqNGh5cm10dzBoRjNrLTJWT080THZXRzBLNEF5a0JYS25HVWciLCJ5IjoiYzlEVHE5cVRWUTlRQmlsLUgxdGRWN3FZZERic3BhTG5wZ0FJdkRKeEpHayJ9#0',
32
+ alg: 'ES256',
33
+ publicKey: {
34
+ kty: 'EC',
35
+ x: 'AXAlZY8j4hyrmtw0hF3k-2VOO4LvWG0K4AykBXKnGUg',
36
+ y: 'c9DTq9qTVQ9QBil-H1tdV7qYdDbspaLnpgAIvDJxJGk',
37
+ crv: 'P-256',
38
+ },
39
+ privateKey: {
40
+ kty: 'EC',
41
+ x: 'AXAlZY8j4hyrmtw0hF3k-2VOO4LvWG0K4AykBXKnGUg',
42
+ y: 'c9DTq9qTVQ9QBil-H1tdV7qYdDbspaLnpgAIvDJxJGk',
43
+ crv: 'P-256',
44
+ d: 'fcZ8We_GOQKA_hC4ovf4UcBnwfcTVkHGwxhN3WDzD7M',
45
+ },
46
+ },
47
+ };
48
+
49
+ const getKeyPair = ({ kid, keyId }) => {
50
+ let matcher;
51
+
52
+ if (!isEmpty(kid)) {
53
+ matcher = { kid };
54
+ } else if (!isEmpty(keyId)) {
55
+ matcher = { id: keyId };
56
+ }
57
+
58
+ const keyPairEntry = flow(filter(matcher), first)(values(keyPairs));
59
+
60
+ if (isEmpty(keyPairEntry)) {
61
+ throw newError(400, 'Key pair not found', {
62
+ errorCode: `invalid_${!isEmpty(kid) ? 'kid' : 'key_id'}`,
63
+ });
64
+ }
65
+
66
+ return pick(['publicKey', 'privateKey', 'alg'], keyPairEntry);
67
+ };
68
+
69
+ const generateJwk = (curve) => {
70
+ return keyPairs[curve];
71
+ };
72
+
73
+ module.exports = { generateJwk, getKeyPair };
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ ...require('./schemas'),
3
+ };
@@ -0,0 +1,30 @@
1
+ const {
2
+ newVendorOfferSchema,
3
+ } = require('@verii/server-credentialagent/src/controllers/operator/tenants/_tenantId/offers/schemas');
4
+ const { filter, omit } = require('lodash/fp');
5
+
6
+ module.exports = (context) => ({
7
+ $schema: 'http://json-schema.org/draft-07/schema#',
8
+ $id: 'https://velocitycareerlabs.io/generate-offers.schema.json',
9
+ title: 'generate-offers',
10
+ description:
11
+ 'A generate offers, is the same as a regular new-vendor-offer, but without required param offer id',
12
+ type: 'object',
13
+ additionalProperties: false,
14
+ properties: {
15
+ ...omit(
16
+ ['offerCreationDate', 'offerExpirationDate'],
17
+ newVendorOfferSchema.properties
18
+ ),
19
+ },
20
+ required: [
21
+ ...filter(
22
+ [
23
+ 'type',
24
+ 'credentialSubject',
25
+ ...(context.config.omitOfferId ? [] : ['offerId']),
26
+ ],
27
+ newVendorOfferSchema.required
28
+ ),
29
+ ],
30
+ });