@cooperation/vc-storage 1.0.10 → 1.0.12
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.
- package/dist/models/CredentialEngine.js +53 -18
- package/dist/models/GoogleDriveStorage.js +160 -128
- package/dist/types/models/CredentialEngine.d.ts +16 -3
- package/dist/types/models/GoogleDriveStorage.d.ts +18 -19
- package/dist/types/utils/credential.d.ts +29 -10
- package/dist/types/utils/google.d.ts +23 -5
- package/dist/utils/credential.js +131 -109
- package/dist/utils/google.js +31 -24
- package/dist/utils/presentation.js +26 -29
- package/package.json +1 -2
- package/dist/types/utils/saveToGoogle.d.ts +0 -10
- package/dist/utils/saveToGoogle.js +0 -65
@@ -1,20 +1,39 @@
|
|
1
1
|
import { KeyPair, DidDocument, FormDataI, RecommendationCredential, Credential, RecommendationFormDataI, VerifiableCredential } from '../../types/credential';
|
2
2
|
/**
|
3
3
|
* Create a DID document using the provided key pair.
|
4
|
-
* @param {
|
5
|
-
* @returns {Promise<
|
4
|
+
* @param {KeyPair} keyPair - The key pair used to create the DID document.
|
5
|
+
* @returns {Promise<DidDocument>} The created DID document.
|
6
|
+
* @throws Will throw an error if the DID document generation fails.
|
6
7
|
*/
|
7
8
|
export declare const generateDIDSchema: (keyPair: KeyPair) => Promise<DidDocument>;
|
8
9
|
/**
|
9
|
-
* Generate an unsigned Verifiable Credential (VC)
|
10
|
-
*
|
11
|
-
* @param {
|
12
|
-
* @param {string}
|
13
|
-
* @
|
14
|
-
* @
|
10
|
+
* Generate an unsigned Verifiable Credential (VC).
|
11
|
+
* Hashes the credential to create a unique ID.
|
12
|
+
* @param {FormDataI} params
|
13
|
+
* @param {string} params.FormData - The form dta to include in the VC.
|
14
|
+
* @param {string} params.issuerDid - The DID of the issuer.
|
15
|
+
* @returns {Credential} The created unsigned VC.
|
16
|
+
* @throws Will throw an error if the VC creation fails or if issuance date exceeds expiration date.
|
15
17
|
*/
|
16
|
-
export declare function generateUnsignedVC(formData
|
17
|
-
|
18
|
+
export declare function generateUnsignedVC({ formData, issuerDid }: {
|
19
|
+
formData: FormDataI;
|
20
|
+
issuerDid: string;
|
21
|
+
}): Credential;
|
22
|
+
/**
|
23
|
+
* Generate an unsigned Recommendation Credential.
|
24
|
+
* Uses the hash of the VC to set the `id` for consistency.
|
25
|
+
* @param {object} params
|
26
|
+
* @param {VerifiableCredential} params.vc - The Verifiable Credential to base the recommendation on.
|
27
|
+
* @param {RecommendationFormDataI} params.recommendation - The recommendation form data.
|
28
|
+
* @param {string} params.issuerDid - The DID of the issuer.
|
29
|
+
* @returns {RecommendationCredential} The created unsigned Recommendation Credential.
|
30
|
+
* @throws Will throw an error if the recommendation creation fails or if issuance date exceeds expiration date.
|
31
|
+
*/
|
32
|
+
export declare function generateUnsignedRecommendation({ vc, recommendation, issuerDid, }: {
|
33
|
+
vc: any;
|
34
|
+
recommendation: RecommendationFormDataI;
|
35
|
+
issuerDid: string;
|
36
|
+
}): RecommendationCredential;
|
18
37
|
/**
|
19
38
|
* Extracts the keypair from a Verifiable Credential
|
20
39
|
* @param {Object} credential - The signed Verifiable Credential
|
@@ -1,15 +1,32 @@
|
|
1
1
|
import { GoogleDriveStorage } from '../models/GoogleDriveStorage.js';
|
2
|
+
export type FileType = 'VC' | 'DID' | 'SESSION' | 'RECOMMENDATION' | 'KEYPAIR';
|
3
|
+
interface SaveToGooglePropsI {
|
4
|
+
storage: GoogleDriveStorage;
|
5
|
+
data: any;
|
6
|
+
type: FileType;
|
7
|
+
vcId?: string;
|
8
|
+
}
|
9
|
+
export declare const getVCWithRecommendations: ({ vcId, storage }: {
|
10
|
+
vcId: string;
|
11
|
+
storage: GoogleDriveStorage;
|
12
|
+
}) => Promise<{
|
13
|
+
vc: {
|
14
|
+
name: string;
|
15
|
+
data: any;
|
16
|
+
id: string;
|
17
|
+
};
|
18
|
+
recommendations: any[];
|
19
|
+
relationsFileId: any;
|
20
|
+
}>;
|
2
21
|
/**
|
3
|
-
* keyFile name = {uuid}-type-timestamp // we need that
|
4
|
-
* vc.id = urn-uuid-{uuid} // we got that
|
5
22
|
* Save data to Google Drive in the specified folder type.
|
6
23
|
* @param {object} data - The data to save.
|
7
|
-
* @param {
|
24
|
+
* @param {FileType} data.type - The type of data being saved.
|
8
25
|
* @returns {Promise<object>} - The file object saved to Google Drive.
|
9
|
-
* @param {string}
|
26
|
+
* @param {string} data.vcId - Optional unique identifier for the VC to link the recommendations.
|
10
27
|
* @throws Will throw an error if the save operation fails.
|
11
28
|
*/
|
12
|
-
export declare function saveToGoogleDrive(storage
|
29
|
+
export declare function saveToGoogleDrive({ storage, data, type }: SaveToGooglePropsI): Promise<any>;
|
13
30
|
/**
|
14
31
|
* Upload an image to Google Drive in the Credentials/MEDIAs folder.
|
15
32
|
* @param {GoogleDriveStorage} storage - The GoogleDriveStorage instance.
|
@@ -22,3 +39,4 @@ export declare function uploadImageToGoogleDrive(storage: GoogleDriveStorage, im
|
|
22
39
|
}>;
|
23
40
|
export declare function generateViewLink(fileId: string): string;
|
24
41
|
export declare function extractGoogleDriveFileId(url: string): string | null;
|
42
|
+
export {};
|
package/dist/utils/credential.js
CHANGED
@@ -1,14 +1,28 @@
|
|
1
1
|
import { Ed25519VerificationKey2020 } from '@digitalbazaar/ed25519-verification-key-2020';
|
2
|
+
import crypto from 'crypto';
|
2
3
|
import { v4 as uuidv4 } from 'uuid';
|
4
|
+
/**
|
5
|
+
* Utility function to generate a hashed ID for a credential.
|
6
|
+
* Excludes the `id` field when hashing.
|
7
|
+
* @param {object} credential - The credential object to hash.
|
8
|
+
* @returns {string} The generated hashed ID.
|
9
|
+
*/
|
10
|
+
function generateHashedId(credential) {
|
11
|
+
// Exclude the `id` field from the hash
|
12
|
+
const credentialWithoutId = { ...credential, id: undefined };
|
13
|
+
const serialized = JSON.stringify(credentialWithoutId);
|
14
|
+
return crypto.createHash('sha256').update(serialized).digest('hex');
|
15
|
+
}
|
3
16
|
/**
|
4
17
|
* Create a DID document using the provided key pair.
|
5
|
-
* @param {
|
6
|
-
* @returns {Promise<
|
18
|
+
* @param {KeyPair} keyPair - The key pair used to create the DID document.
|
19
|
+
* @returns {Promise<DidDocument>} The created DID document.
|
20
|
+
* @throws Will throw an error if the DID document generation fails.
|
7
21
|
*/
|
8
22
|
export const generateDIDSchema = async (keyPair) => {
|
9
23
|
try {
|
10
24
|
const DID = keyPair.controller;
|
11
|
-
|
25
|
+
return {
|
12
26
|
'@context': ['https://www.w3.org/ns/did/v1'],
|
13
27
|
id: DID,
|
14
28
|
publicKey: [
|
@@ -32,7 +46,6 @@ export const generateDIDSchema = async (keyPair) => {
|
|
32
46
|
},
|
33
47
|
],
|
34
48
|
};
|
35
|
-
return didDocument;
|
36
49
|
}
|
37
50
|
catch (error) {
|
38
51
|
console.error('Error creating DID document:', error);
|
@@ -40,117 +53,126 @@ export const generateDIDSchema = async (keyPair) => {
|
|
40
53
|
}
|
41
54
|
};
|
42
55
|
/**
|
43
|
-
* Generate an unsigned Verifiable Credential (VC)
|
44
|
-
*
|
45
|
-
* @param {
|
46
|
-
* @param {string}
|
47
|
-
* @
|
48
|
-
* @
|
56
|
+
* Generate an unsigned Verifiable Credential (VC).
|
57
|
+
* Hashes the credential to create a unique ID.
|
58
|
+
* @param {FormDataI} params
|
59
|
+
* @param {string} params.FormData - The form dta to include in the VC.
|
60
|
+
* @param {string} params.issuerDid - The DID of the issuer.
|
61
|
+
* @returns {Credential} The created unsigned VC.
|
62
|
+
* @throws Will throw an error if the VC creation fails or if issuance date exceeds expiration date.
|
49
63
|
*/
|
50
|
-
export function generateUnsignedVC(formData, issuerDid
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
'
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
credentialType: 'https://schema.org/credentialType',
|
66
|
-
},
|
67
|
-
],
|
68
|
-
id: `urn:uuid:${vcId}`, //! i want this uuid to be in the condition where vcId part == keypair file name which is like this `${uuid ? uuid + '_' : ''}${type}_${timestamp}.json`,
|
69
|
-
type: ['VerifiableCredential', 'OpenBadgeCredential'],
|
70
|
-
issuer: {
|
71
|
-
id: issuerDid,
|
72
|
-
type: ['Profile'],
|
64
|
+
export function generateUnsignedVC({ formData, issuerDid }) {
|
65
|
+
const issuanceDate = new Date().toISOString();
|
66
|
+
if (issuanceDate > formData.expirationDate)
|
67
|
+
throw new Error('issuanceDate cannot be after expirationDate');
|
68
|
+
const unsignedCredential = {
|
69
|
+
'@context': [
|
70
|
+
'https://www.w3.org/2018/credentials/v1',
|
71
|
+
'https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json',
|
72
|
+
{
|
73
|
+
duration: 'https://schema.org/duration',
|
74
|
+
fullName: 'https://schema.org/name',
|
75
|
+
portfolio: 'https://schema.org/portfolio',
|
76
|
+
evidenceLink: 'https://schema.org/evidenceLink',
|
77
|
+
evidenceDescription: 'https://schema.org/evidenceDescription',
|
78
|
+
credentialType: 'https://schema.org/credentialType',
|
73
79
|
},
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
type: 'Image',
|
97
|
-
}
|
98
|
-
: undefined,
|
99
|
-
},
|
100
|
-
],
|
101
|
-
},
|
102
|
-
};
|
103
|
-
return unsignedCredential;
|
104
|
-
}
|
105
|
-
catch (error) {
|
106
|
-
console.error('Error creating unsigned VC', error);
|
107
|
-
throw error;
|
108
|
-
}
|
109
|
-
}
|
110
|
-
export function generateUnsignedRecommendation(recommendation, issuerDid) {
|
111
|
-
try {
|
112
|
-
const issuanceDate = new Date().toISOString();
|
113
|
-
if (issuanceDate > recommendation.expirationDate)
|
114
|
-
throw Error('issuanceDate cannot be after expirationDate');
|
115
|
-
const unsignedRecommendation = {
|
116
|
-
'@context': [
|
117
|
-
'https://www.w3.org/2018/credentials/v1',
|
118
|
-
'https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json',
|
80
|
+
],
|
81
|
+
id: '', // Will be set after hashing
|
82
|
+
type: ['VerifiableCredential', 'OpenBadgeCredential'],
|
83
|
+
issuer: {
|
84
|
+
id: issuerDid,
|
85
|
+
type: ['Profile'],
|
86
|
+
},
|
87
|
+
issuanceDate,
|
88
|
+
expirationDate: formData.expirationDate,
|
89
|
+
credentialSubject: {
|
90
|
+
type: ['AchievementSubject'],
|
91
|
+
name: formData.fullName,
|
92
|
+
portfolio: formData.portfolio.map((item) => ({
|
93
|
+
'@type': 'schema:CreativeWork',
|
94
|
+
name: item.name,
|
95
|
+
url: item.url,
|
96
|
+
})),
|
97
|
+
evidenceLink: formData.evidenceLink,
|
98
|
+
evidenceDescription: formData.achievementDescription,
|
99
|
+
duration: formData.duration,
|
100
|
+
credentialType: formData.credentialType,
|
101
|
+
achievement: [
|
119
102
|
{
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
103
|
+
id: `urn:uuid:${uuidv4()}`,
|
104
|
+
type: ['Achievement'],
|
105
|
+
criteria: {
|
106
|
+
narrative: formData.criteriaNarrative,
|
107
|
+
},
|
108
|
+
description: formData.achievementDescription,
|
109
|
+
name: formData.achievementName,
|
110
|
+
image: formData.evidenceLink
|
111
|
+
? {
|
112
|
+
id: formData.evidenceLink,
|
113
|
+
type: 'Image',
|
114
|
+
}
|
115
|
+
: undefined,
|
125
116
|
},
|
126
117
|
],
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
118
|
+
},
|
119
|
+
};
|
120
|
+
// Generate the hashed ID
|
121
|
+
unsignedCredential.id = 'urn:' + generateHashedId(unsignedCredential);
|
122
|
+
return unsignedCredential;
|
123
|
+
}
|
124
|
+
/**
|
125
|
+
* Generate an unsigned Recommendation Credential.
|
126
|
+
* Uses the hash of the VC to set the `id` for consistency.
|
127
|
+
* @param {object} params
|
128
|
+
* @param {VerifiableCredential} params.vc - The Verifiable Credential to base the recommendation on.
|
129
|
+
* @param {RecommendationFormDataI} params.recommendation - The recommendation form data.
|
130
|
+
* @param {string} params.issuerDid - The DID of the issuer.
|
131
|
+
* @returns {RecommendationCredential} The created unsigned Recommendation Credential.
|
132
|
+
* @throws Will throw an error if the recommendation creation fails or if issuance date exceeds expiration date.
|
133
|
+
*/
|
134
|
+
export function generateUnsignedRecommendation({ vc, recommendation, issuerDid, }) {
|
135
|
+
console.log('🚀 ~ vc.id:', vc.id);
|
136
|
+
console.log('🚀 ~ vc:', vc);
|
137
|
+
console.log('🚀 ~ recommendation:', recommendation);
|
138
|
+
const issuanceDate = new Date().toISOString();
|
139
|
+
if (issuanceDate > recommendation.expirationDate)
|
140
|
+
throw new Error('issuanceDate cannot be after expirationDate');
|
141
|
+
const unsignedRecommendation = {
|
142
|
+
'@context': [
|
143
|
+
'https://www.w3.org/2018/credentials/v1',
|
144
|
+
'https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json',
|
145
|
+
{
|
146
|
+
howKnow: 'https://schema.org/howKnow',
|
147
|
+
recommendationText: 'https://schema.org/recommendationText',
|
148
|
+
qualifications: 'https://schema.org/qualifications',
|
149
|
+
explainAnswer: 'https://schema.org/explainAnswer',
|
150
|
+
portfolio: 'https://schema.org/portfolio',
|
145
151
|
},
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
152
|
+
],
|
153
|
+
id: '', // Will be set after hashing VC
|
154
|
+
type: ['VerifiableCredential', 'https://schema.org/RecommendationCredential'],
|
155
|
+
issuer: {
|
156
|
+
id: issuerDid,
|
157
|
+
type: ['Profile'],
|
158
|
+
},
|
159
|
+
issuanceDate,
|
160
|
+
expirationDate: recommendation.expirationDate,
|
161
|
+
credentialSubject: {
|
162
|
+
name: recommendation.fullName,
|
163
|
+
howKnow: recommendation.howKnow,
|
164
|
+
recommendationText: recommendation.recommendationText,
|
165
|
+
qualifications: recommendation.qualifications,
|
166
|
+
explainAnswer: recommendation.explainAnswer,
|
167
|
+
portfolio: recommendation.portfolio.map((item) => ({
|
168
|
+
name: item.name,
|
169
|
+
url: item.url,
|
170
|
+
})),
|
171
|
+
},
|
172
|
+
};
|
173
|
+
// Use the VC's hashed ID for the Recommendation's ID
|
174
|
+
unsignedRecommendation.id = vc.data.id;
|
175
|
+
return unsignedRecommendation;
|
154
176
|
}
|
155
177
|
/**
|
156
178
|
* Extracts the keypair from a Verifiable Credential
|
package/dist/utils/google.js
CHANGED
@@ -1,18 +1,29 @@
|
|
1
|
+
export const getVCWithRecommendations = async ({ vcId, storage }) => {
|
2
|
+
const vcFolderId = await storage.getFileParents(vcId);
|
3
|
+
const files = await storage.findFilesUnderFolder(vcFolderId);
|
4
|
+
const relationsFile = files.find((f) => f.name === 'RELATIONS');
|
5
|
+
const relationsContent = await storage.retrieve(relationsFile.id);
|
6
|
+
const relationsData = relationsContent.data;
|
7
|
+
const [vcFileId, recommendationIds] = [relationsData.vc_id, relationsData.recommendations];
|
8
|
+
const vc = await storage.retrieve(vcFileId);
|
9
|
+
const recommendations = await Promise.all(recommendationIds.map(async (rec) => {
|
10
|
+
const recFile = await storage.retrieve(rec);
|
11
|
+
return recFile;
|
12
|
+
}));
|
13
|
+
return { vc: vc, recommendations, relationsFileId: relationsFile.id };
|
14
|
+
};
|
1
15
|
/**
|
2
|
-
* keyFile name = {uuid}-type-timestamp // we need that
|
3
|
-
* vc.id = urn-uuid-{uuid} // we got that
|
4
16
|
* Save data to Google Drive in the specified folder type.
|
5
17
|
* @param {object} data - The data to save.
|
6
|
-
* @param {
|
18
|
+
* @param {FileType} data.type - The type of data being saved.
|
7
19
|
* @returns {Promise<object>} - The file object saved to Google Drive.
|
8
|
-
* @param {string}
|
20
|
+
* @param {string} data.vcId - Optional unique identifier for the VC to link the recommendations.
|
9
21
|
* @throws Will throw an error if the save operation fails.
|
10
22
|
*/
|
11
|
-
export async function saveToGoogleDrive(storage, data, type
|
23
|
+
export async function saveToGoogleDrive({ storage, data, type }) {
|
12
24
|
try {
|
13
|
-
const timestamp = Date.now();
|
14
25
|
const fileData = {
|
15
|
-
fileName:
|
26
|
+
fileName: type === 'VC' ? 'VC' : `${type}-${Date.now()}`,
|
16
27
|
mimeType: 'application/json',
|
17
28
|
body: JSON.stringify(data),
|
18
29
|
};
|
@@ -24,34 +35,31 @@ export async function saveToGoogleDrive(storage, data, type, uuid) {
|
|
24
35
|
let credentialsFolderId;
|
25
36
|
if (!credentialsFolder) {
|
26
37
|
credentialsFolderId = await storage.createFolder('Credentials');
|
27
|
-
console.log('Created Credentials folder with ID:', credentialsFolderId);
|
28
38
|
}
|
29
39
|
else {
|
30
40
|
credentialsFolderId = credentialsFolder.id;
|
31
|
-
console.log('Found Credentials folder with ID:', credentialsFolderId);
|
32
41
|
}
|
33
42
|
// Get subfolders within the "Credentials" folder
|
34
43
|
const subfolders = await storage.findFolders(credentialsFolderId);
|
35
|
-
console.log(`Subfolders in Credentials (ID: ${credentialsFolderId}):`, subfolders);
|
36
44
|
// Find or create the specific subfolder (DIDs or VCs)
|
37
45
|
let typeFolder = subfolders.find((f) => f.name === `${type}s`);
|
38
46
|
let typeFolderId;
|
39
47
|
if (!typeFolder) {
|
40
48
|
typeFolderId = await storage.createFolder(`${type}s`, credentialsFolderId);
|
41
|
-
console.log(`Created ${type}s folder with ID:`, typeFolderId);
|
42
49
|
}
|
43
50
|
else {
|
44
51
|
typeFolderId = typeFolder.id;
|
45
|
-
|
46
|
-
|
52
|
+
}
|
53
|
+
if (type === 'VC') {
|
54
|
+
// save the data in Credentials/VCs/VC-timestamp/vc.json
|
55
|
+
const vcFolderId = await storage.createFolder(`${fileData.fileName}-${Date.now()}`, typeFolderId);
|
56
|
+
const file = await storage.saveFile({ data: fileData, folderId: vcFolderId });
|
57
|
+
console.log(`File uploaded: ${file?.id} under ${fileData.fileName} folder in VCs folder`);
|
58
|
+
return file;
|
47
59
|
}
|
48
60
|
// Save the file in the specific subfolder
|
49
|
-
const file = await storage.
|
61
|
+
const file = await storage.saveFile({ data: fileData, folderId: typeFolderId });
|
50
62
|
console.log(`File uploaded: ${file?.id} under ${type}s with ID ${typeFolderId} folder in Credentials folder`);
|
51
|
-
if (file && file.id) {
|
52
|
-
console.log('Sharing file with second user...');
|
53
|
-
await storage.addCommenterRoleToFile(file.id);
|
54
|
-
}
|
55
63
|
return file;
|
56
64
|
}
|
57
65
|
catch (error) {
|
@@ -68,9 +76,7 @@ export async function saveToGoogleDrive(storage, data, type, uuid) {
|
|
68
76
|
*/
|
69
77
|
export async function uploadImageToGoogleDrive(storage, imageFile) {
|
70
78
|
try {
|
71
|
-
// Get all root folders
|
72
79
|
const rootFolders = await storage.findFolders();
|
73
|
-
// Find or create the "Credentials" folder
|
74
80
|
let credentialsFolder = rootFolders.find((f) => f.name === 'Credentials');
|
75
81
|
let credentialsFolderId;
|
76
82
|
if (!credentialsFolder) {
|
@@ -79,9 +85,7 @@ export async function uploadImageToGoogleDrive(storage, imageFile) {
|
|
79
85
|
else {
|
80
86
|
credentialsFolderId = credentialsFolder.id;
|
81
87
|
}
|
82
|
-
// Get subfolders within the "Credentials" folder
|
83
88
|
const subfolders = await storage.findFolders(credentialsFolderId);
|
84
|
-
// Find or create the "MEDIAs" folder
|
85
89
|
let mediasFolder = subfolders.find((f) => f.name === 'MEDIAs');
|
86
90
|
let mediasFolderId;
|
87
91
|
if (!mediasFolder) {
|
@@ -96,8 +100,11 @@ export async function uploadImageToGoogleDrive(storage, imageFile) {
|
|
96
100
|
mimeType: imageFile.type,
|
97
101
|
body: imageFile,
|
98
102
|
};
|
99
|
-
//
|
100
|
-
const uploadedImage = await storage.
|
103
|
+
// SaveFile the image in the "MEDIAs" folder
|
104
|
+
const uploadedImage = await storage.saveFile({
|
105
|
+
data: imageData,
|
106
|
+
folderId: mediasFolderId,
|
107
|
+
});
|
101
108
|
console.log(`Image uploaded: ${uploadedImage?.id} to MEDIAs folder in Credentials`);
|
102
109
|
return uploadedImage;
|
103
110
|
}
|
@@ -1,6 +1,3 @@
|
|
1
|
-
import { CredentialEngine } from '../models/CredentialEngine.js';
|
2
|
-
import { GoogleDriveStorage } from '../models/GoogleDriveStorage.js';
|
3
|
-
import { extractGoogleDriveFileId } from './google.js';
|
4
1
|
/**
|
5
2
|
* Create and sign a Verifiable Presentation (VP) from a given Verifiable Credential (VC) file and any associated recommendations.
|
6
3
|
* @param {string} accessTokens - The access tokens for the user.
|
@@ -14,32 +11,32 @@ export const createAndSignVerifiablePresentation = async (accessTokens, vcFileId
|
|
14
11
|
return null;
|
15
12
|
}
|
16
13
|
try {
|
17
|
-
const storage = new GoogleDriveStorage(accessTokens);
|
18
|
-
const engine = new CredentialEngine(accessTokens);
|
19
|
-
// Fetch Verifiable Credential (VC)
|
20
|
-
const verifiableCredential = await storage.retrieve(vcFileId);
|
21
|
-
if (!verifiableCredential) {
|
22
|
-
|
23
|
-
}
|
24
|
-
// Fetch VC comments (potential recommendations)
|
25
|
-
const verifiableCredentialComments = await storage.getFileComments(vcFileId);
|
26
|
-
let recommendations = [];
|
27
|
-
// Extract recommendations from comments if present
|
28
|
-
if (verifiableCredentialComments.length > 0) {
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
}
|
38
|
-
// Create Verifiable Presentation (VP) with the retrieved VC
|
39
|
-
const presentation = await engine.createPresentation([verifiableCredential.data, ...recommendations]); //! do not edit the array order!!
|
40
|
-
// Use the key pair to sign the presentation
|
41
|
-
const signedPresentation = await engine.signPresentation(presentation);
|
42
|
-
return {
|
14
|
+
// const storage = new GoogleDriveStorage(accessTokens);
|
15
|
+
// const engine = new CredentialEngine(accessTokens);
|
16
|
+
// // Fetch Verifiable Credential (VC)
|
17
|
+
// const verifiableCredential = await storage.retrieve(vcFileId);
|
18
|
+
// if (!verifiableCredential) {
|
19
|
+
// throw new Error('Verifiable Credential not found.');
|
20
|
+
// }
|
21
|
+
// // Fetch VC comments (potential recommendations)
|
22
|
+
// const verifiableCredentialComments = await storage.getFileComments(vcFileId);
|
23
|
+
// let recommendations: object[] = [];
|
24
|
+
// // Extract recommendations from comments if present
|
25
|
+
// if (verifiableCredentialComments.length > 0) {
|
26
|
+
// for (const comment of verifiableCredentialComments) {
|
27
|
+
// console.log('🚀 ~ createAndSignVerifiablePresentation ~ comment', comment);
|
28
|
+
// const recommendationFile = await storage.retrieve(extractGoogleDriveFileId(comment.content));
|
29
|
+
// console.log('🚀 ~ createAndSignVerifiablePresentation ~ recommendationFile', recommendationFile);
|
30
|
+
// if (recommendationFile) {
|
31
|
+
// recommendations.push(recommendationFile);
|
32
|
+
// }
|
33
|
+
// }
|
34
|
+
// }
|
35
|
+
// // Create Verifiable Presentation (VP) with the retrieved VC
|
36
|
+
// const presentation = await engine.createPresentation([verifiableCredential.data, ...recommendations]); //! do not edit the array order!!
|
37
|
+
// // Use the key pair to sign the presentation
|
38
|
+
// const signedPresentation = await engine.signPresentation(presentation);
|
39
|
+
// return {};
|
43
40
|
}
|
44
41
|
catch (error) {
|
45
42
|
console.error('Error during Verifiable Presentation creation and signing:', error);
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@cooperation/vc-storage",
|
3
3
|
"type": "module",
|
4
|
-
"version": "1.0.
|
4
|
+
"version": "1.0.12",
|
5
5
|
"description": "Sign and store your verifiable credentials.",
|
6
6
|
"main": "dist/index.js",
|
7
7
|
"types": "dist/types/index.d.ts",
|
@@ -16,7 +16,6 @@
|
|
16
16
|
"author": "cooperation",
|
17
17
|
"license": "ISC",
|
18
18
|
"dependencies": {
|
19
|
-
"@cooperation/vc-storage": "^1.0.6",
|
20
19
|
"@digitalbazaar/did-method-key": "^5.2.0",
|
21
20
|
"@digitalbazaar/ed25519-signature-2020": "^5.3.0",
|
22
21
|
"@digitalbazaar/ed25519-verification-key-2020": "^4.1.0",
|
@@ -1,10 +0,0 @@
|
|
1
|
-
import { GoogleDriveStorage } from '../models/GoogleDriveStorage.js';
|
2
|
-
/**
|
3
|
-
* Save data to Google Drive in the specified folder type.
|
4
|
-
* @param {object} data - The data to save.
|
5
|
-
* @param {'VC' | 'DID' | 'UnsignedVC'} type - The type of data being saved.
|
6
|
-
* @returns {Promise<object>} - The file object saved to Google Drive.
|
7
|
-
* @throws Will throw an error if the save operation fails.
|
8
|
-
*/
|
9
|
-
export declare function saveToGoogleDrive(storage: GoogleDriveStorage, data: any, type: 'VC' | 'DID' | 'SESSION' | 'RECOMMENDATION'): Promise<object>;
|
10
|
-
export declare function generateViewLink(fileId: string): string;
|
@@ -1,65 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Save data to Google Drive in the specified folder type.
|
3
|
-
* @param {object} data - The data to save.
|
4
|
-
* @param {'VC' | 'DID' | 'UnsignedVC'} type - The type of data being saved.
|
5
|
-
* @returns {Promise<object>} - The file object saved to Google Drive.
|
6
|
-
* @throws Will throw an error if the save operation fails.
|
7
|
-
*/
|
8
|
-
export async function saveToGoogleDrive(storage, data, type) {
|
9
|
-
try {
|
10
|
-
const timestamp = Date.now();
|
11
|
-
const fileData = {
|
12
|
-
fileName: `${type}-${timestamp}.json`,
|
13
|
-
mimeType: 'application/json',
|
14
|
-
body: JSON.stringify(data),
|
15
|
-
};
|
16
|
-
// Get all root folders
|
17
|
-
const rootFolders = await storage.findFolders();
|
18
|
-
console.log('Root folders:', rootFolders);
|
19
|
-
// Find or create the "Credentials" folder
|
20
|
-
let credentialsFolder = rootFolders.find((f) => f.name === 'Credentials');
|
21
|
-
let credentialsFolderId;
|
22
|
-
if (!credentialsFolder) {
|
23
|
-
credentialsFolderId = await storage.createFolder('Credentials');
|
24
|
-
console.log('Created Credentials folder with ID:', credentialsFolderId);
|
25
|
-
}
|
26
|
-
else {
|
27
|
-
credentialsFolderId = credentialsFolder.id;
|
28
|
-
console.log('Found Credentials folder with ID:', credentialsFolderId);
|
29
|
-
}
|
30
|
-
// Get subfolders within the "Credentials" folder
|
31
|
-
const subfolders = await storage.findFolders(credentialsFolderId);
|
32
|
-
console.log(`Subfolders in Credentials (ID: ${credentialsFolderId}):`, subfolders);
|
33
|
-
// Find or create the specific subfolder (DIDs or VCs)
|
34
|
-
let typeFolder = subfolders.find((f) => f.name === `${type}s`);
|
35
|
-
let typeFolderId;
|
36
|
-
if (!typeFolder) {
|
37
|
-
typeFolderId = await storage.createFolder(`${type}s`, credentialsFolderId);
|
38
|
-
console.log(`Created ${type}s folder with ID:`, typeFolderId);
|
39
|
-
}
|
40
|
-
else {
|
41
|
-
typeFolderId = typeFolder.id;
|
42
|
-
console.log(`Found ${type} files:`, await storage.findLastFile(typeFolderId));
|
43
|
-
console.log(`Found ${type}s folder with ID:`, typeFolderId);
|
44
|
-
}
|
45
|
-
// Save the file in the specific subfolder
|
46
|
-
const file = await storage.save(fileData, typeFolderId);
|
47
|
-
console.log(`File uploaded: ${file?.id} under ${type}s with ID ${typeFolderId} folder in Credentials folder`);
|
48
|
-
if (file && file.id) {
|
49
|
-
console.log('Sharing file with second user...');
|
50
|
-
await storage.addCommenterRoleToFile(file.id);
|
51
|
-
}
|
52
|
-
return file;
|
53
|
-
}
|
54
|
-
catch (error) {
|
55
|
-
console.error('Error saving to Google Drive:', error);
|
56
|
-
throw error;
|
57
|
-
}
|
58
|
-
}
|
59
|
-
export function generateViewLink(fileId) {
|
60
|
-
if (!fileId) {
|
61
|
-
throw new Error('File ID is required to generate a view link.');
|
62
|
-
}
|
63
|
-
// Construct the view URL based on the file ID
|
64
|
-
return `https://drive.google.com/file/d/${fileId}/view`;
|
65
|
-
}
|