diff --git a/.gitignore b/.gitignore index 9b09a5f..1f7a204 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build/ node_modules/ -.env \ No newline at end of file +.env +.vscode/settings.json diff --git a/src/files/files.controller.ts b/src/files/files.controller.ts index fc47b81..04de24f 100644 --- a/src/files/files.controller.ts +++ b/src/files/files.controller.ts @@ -1,7 +1,7 @@ import fileUpload from 'express-fileupload'; import {StorageOperationController} from '../hyperledger/StorageOperationController'; import ipfsService from '../ipfs/ipfs.service'; -import {MFSEntry} from 'ipfs-core-types/src/files'; +import {KFSEntry} from './files.interfaces'; class FilesController { async createFile(userId: string, file: fileUpload.UploadedFile) { @@ -11,13 +11,13 @@ class FilesController { try { return await ipfsService .createFile(userId, file) - .then((files: MFSEntry[]) => { + .then((files: KFSEntry[]) => { console.log('[DEBUG] files.controller - createFile: files', files); - files.forEach((file: MFSEntry) => { + files.forEach((file: KFSEntry) => { new StorageOperationController().createFileOperation( userId, - file.cid.toString(), + file.id, 'WRITE' ); }); @@ -36,13 +36,13 @@ class FilesController { `[INFO] files.controller - listFiles: Listing files for userId ${userId}` ); try { - return await ipfsService.listFiles().then((files: MFSEntry[]) => { + return await ipfsService.listFiles().then((files: KFSEntry[]) => { console.log('[DEBUG] files.controller - listFiles: files', files); - files.forEach((file: MFSEntry) => { + files.forEach((file: KFSEntry) => { new StorageOperationController().createFileOperation( userId, - file.cid.toString(), + file.id, 'READ' ); }); diff --git a/src/files/files.interfaces.ts b/src/files/files.interfaces.ts new file mode 100644 index 0000000..60eb606 --- /dev/null +++ b/src/files/files.interfaces.ts @@ -0,0 +1,7 @@ +import {MFSEntry} from 'ipfs-core-types/src/files'; + +export interface KFSEntry extends MFSEntry { + // Kinto File System Entry + id: string; + txHistory?: Array; +} diff --git a/src/files/files.routes.config.ts b/src/files/files.routes.config.ts index eb8836d..7a63c4a 100644 --- a/src/files/files.routes.config.ts +++ b/src/files/files.routes.config.ts @@ -10,6 +10,7 @@ export class FilesRoutes extends CommonRoutesConfig { } configureRoutes() { this.app + // Logic for folders .route(`/${USERS}/:userId/${FILES}`) .all((req: Request, res: Response, next: NextFunction) => { // Middleware executed on every route. @TODO: Validation @TODO: User authentication @TODO: Register on Hyperledger @@ -55,13 +56,14 @@ export class FilesRoutes extends CommonRoutesConfig { next(); }) .get((req: Request, res: Response) => { + // @TODO: Logic for folders const fileCID = req.params.fileId; - if (!fileCID) res.status(400).send('File CID must be set!'); + if (!fileCID) return res.status(400).send('File CID must be set!'); - const userId = req.body.userId; - if (!userId) res.status(400).send('Missing userId'); + const userId = req.params.userId; + if (!userId) return res.status(400).send('Missing userId'); - filesController + return filesController .getFile(userId, fileCID) .then(file => res.status(200).send(file)) .catch(error => @@ -70,7 +72,9 @@ export class FilesRoutes extends CommonRoutesConfig { }) // @TODO: Define if possible .patch((req: Request, res: Response) => { - res.status(200).send(`TODO: PATCH file for id ${req.params.fileId}`); + return res + .status(200) + .send(`TODO: PATCH file for id ${req.params.fileId}`); }) // @TODO: this uses filename and it's not really usable in a multiple-node context. // @TODO: will make more sense for it to use :fileId BUT you can't delete files with the CID... not really sure why diff --git a/src/files/mock/files.ts b/src/files/mock/files.ts new file mode 100644 index 0000000..4590460 --- /dev/null +++ b/src/files/mock/files.ts @@ -0,0 +1,74 @@ +import {CID} from 'multiformats/cid'; +import {KFSEntry} from '../files.interfaces'; + +export const mockListOfFiles: Array = [ + { + name: 'Picture.jpg', + type: 'file', + size: 39393993, + cid: CID.parse( + 'bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqasf3oclgtqy55fbzdi' + ), + id: 'bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqasf3oclgtqy55fbzdi', + }, + { + name: 'movie.mov', + type: 'file', + size: 123123, + cid: CID.parse( + 'bafybeigdyrzt5sfp7udm7hu76uh7y26df3efuylqabf3oclgtqy55fbzdi' + ), + id: 'bafybeigdyrzt5sfp7udm7hu76uh7y26df3efuylqabf3oclgtqy55fbzdi', + }, + { + name: 'file.doc', + type: 'file', + size: 448389289, + cid: CID.parse( + 'bafybeigdyrzt5sfp7udm7hu76uh7y26nf3eduylqabf3oclgtqy55fbzdi' + ), + id: 'bafybeigdyrzt5sfp7udm7hu76uh7y26nf3eduylqabf3oclgtqy55fbzdi', + }, + { + name: 'excel.xslx', + type: 'file', + size: 123123123, + cid: CID.parse( + 'bafybeigdyrzt5sfp7udm7hu76uh7y26nfrefuylqabf3oclgtqy55fbzdi' + ), + id: 'bafybeigdyrzt5sfp7udm7hu76uh7y26nfrefuylqabf3oclgtqy55fbzdi', + }, + { + name: 'printer.pdf', + type: 'file', + size: 123123123154, + cid: CID.parse( + 'bafybeigdyrzt5sfp7udm7hu76uh7y26nv3efuylqabf3oclgtqy55fbzdi' + ), + id: 'bafybeigdyrzt5sfp7udm7hu76uh7y26nv3efuylqabf3oclgtqy55fbzdi', + }, + { + name: 'MyFolder', + type: 'directory', + size: 8, + cid: CID.parse( + 'bafybeigdyrzt5sfp7udm7hu76uh7y26nf3qfuylqabf3oclgtqy55fbzdi' + ), + id: 'bafybeigdyrzt5sfp7udm7hu76uh7y26nf3qfuylqabf3oclgtqy55fbzdi', + }, +]; + +export const mockSingleFile = mockListOfFiles[0]; + +export const mocksNewFileList = [ + ...mockListOfFiles, + { + name: 'Extrafile.png', + type: 'file', + size: 12312312345, + cid: CID.parse( + 'bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efualqabf3oclgtqy55fbzdi' + ), + id: 'bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efualqabf3oclgtqy55fbzdi', + }, +]; diff --git a/src/hyperledger/StorageOperationController.ts b/src/hyperledger/StorageOperationController.ts index 4c22ebc..824da37 100644 --- a/src/hyperledger/StorageOperationController.ts +++ b/src/hyperledger/StorageOperationController.ts @@ -1,6 +1,5 @@ import {HyperledgerController} from './HyperledgerController'; import {StorageOperation} from './contracts/StorageOperation.interface'; -import { StorageController } from '../StorageController'; export class StorageOperationController { //TODO we can use this to show / check history diff --git a/src/ipfs/ipfs.service.ts b/src/ipfs/ipfs.service.ts index 447d7be..fc1e26c 100644 --- a/src/ipfs/ipfs.service.ts +++ b/src/ipfs/ipfs.service.ts @@ -2,6 +2,7 @@ import {UploadedFile} from 'express-fileupload'; import {MFSEntry} from 'ipfs-core-types/src/files'; import {create, IPFSHTTPClient} from 'ipfs-http-client'; import all from 'it-all'; +import {KFSEntry} from '../files/files.interfaces'; /** * @TODO: Better error handling */ @@ -33,7 +34,7 @@ class IPFSService { public async createFile( userId: string, file: UploadedFile - ): Promise { + ): Promise { const filePath = `/${file.name}`; console.log('[DEBUG] IPFSService - createFile', userId, file); @@ -49,9 +50,11 @@ class IPFSService { * @returns Array w/ the results from the node * @TODO: will have to change once userId is implemented */ - public async listFiles(dir = '/'): Promise { + public async listFiles(dir = '/'): Promise { console.log('[DEBUG] IPFSService - listFiles'); - return await all(IPFSService.ipfsHttpClient.files.ls(dir)); + return await ( + await all(IPFSService.ipfsHttpClient.files.ls(dir)) + ).map(file => this.ipfsToKinto(file)); } /** @@ -80,7 +83,7 @@ class IPFSService { * @returns */ public async updateFile(file: File) { - const result: Array = []; + const result: Array = []; // IPFSService.ipfsHttpClient.files.write('/' + file.name, file); // result.push(...(await all(IPFSService.ipfsHttpClient.files.ls(file.name)))); return result; @@ -100,6 +103,10 @@ class IPFSService { throw error; }); } + + private ipfsToKinto(file: MFSEntry) { + return {...file, id: file.cid.toString()}; + } } export default new IPFSService(); diff --git a/tsconfig.json b/tsconfig.json index a213bb6..9781266 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -33,7 +33,7 @@ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - "types": [], /* Specify type package names to be included without being referenced in a source file. */ + "types": ["jest"], /* Specify type package names to be included without being referenced in a source file. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ // "resolveJsonModule": true, /* Enable importing .json files. */