@cooperation/vc-storage 1.0.10 → 1.0.12
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
}
|