-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #669 from Chia-Network/feature/gisdata
Feature/gisdata
- Loading branch information
Showing
19 changed files
with
405 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import _ from 'lodash'; | ||
|
||
import crypto from 'crypto'; | ||
import { FileStore } from '../models'; | ||
|
||
export const getFileList = async (req, res) => { | ||
try { | ||
const files = await FileStore.getFileStoreList(); | ||
res.json(files); | ||
} catch (error) { | ||
res.status(400).json({ | ||
message: 'Can not retreive file list from filestore', | ||
error: error.message, | ||
}); | ||
} | ||
}; | ||
|
||
export const deleteFile = async (req, res) => { | ||
try { | ||
await FileStore.deleteFileStorItem(req.params.fileId); | ||
res.status(204).end(); | ||
} catch (error) { | ||
res.status(400).json({ | ||
message: 'Can not delete file from filestore', | ||
error: error.message, | ||
}); | ||
} | ||
}; | ||
|
||
export const getFile = async (req, res) => { | ||
try { | ||
const { fileId } = req.body; | ||
const file = await FileStore.getFileStoreItem(fileId); | ||
if (file) { | ||
const download = Buffer.from(file.toString('utf-8'), 'base64'); | ||
res.end(download); | ||
} else { | ||
res.status(400).json({ | ||
message: `FileId ${fileId} not found in the filestore.`, | ||
}); | ||
} | ||
} catch (error) { | ||
res.status(400).json({ | ||
message: 'Can not retreive file list from filestore', | ||
error: error.message, | ||
}); | ||
} | ||
}; | ||
|
||
export const addFileToFileStore = async (req, res) => { | ||
try { | ||
if (_.get(req, 'files.file.data')) { | ||
const { fileName } = req.body; | ||
if (!fileName) { | ||
throw new Error('Missing file name, can not upload file'); | ||
} | ||
const buffer = req.files.file.data; | ||
const base64File = buffer.toString('base64'); | ||
const SHA256 = crypto | ||
.createHash('sha256') | ||
.update(base64File) | ||
.digest('base64'); | ||
await FileStore.addFileToFileStore(SHA256, fileName, base64File); | ||
return res.json({ | ||
message: | ||
'File is being added to the file store, please wait for it to confirm.', | ||
}); | ||
} else { | ||
throw new Error('Missing file data, can not upload file.'); | ||
} | ||
} catch (error) { | ||
console.trace(error); | ||
res.status(400).json({ | ||
message: 'Can not add file to file store', | ||
error: error.message, | ||
}); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
src/database/migrations/20220724212553-create-file-store.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
'use strict'; | ||
|
||
import { uuid as uuidv4 } from 'uuidv4'; | ||
|
||
export default { | ||
async up(queryInterface, Sequelize) { | ||
await Promise.all([ | ||
queryInterface.addColumn('organizations', 'fileStoreId', { | ||
type: Sequelize.STRING, | ||
allowNull: true, | ||
}), | ||
queryInterface.addColumn('projectLocations', 'fileId', { | ||
type: Sequelize.STRING, | ||
allowNull: true, | ||
}), | ||
queryInterface.createTable('fileStore', { | ||
SHA256: { | ||
type: Sequelize.STRING, | ||
allowNull: false, | ||
unique: true, | ||
defaultValue: () => uuidv4(), | ||
primaryKey: true, | ||
}, | ||
fileName: { | ||
type: Sequelize.STRING, | ||
unique: true, | ||
}, | ||
data: Sequelize.STRING, | ||
orgUid: Sequelize.STRING, | ||
}), | ||
]); | ||
}, | ||
|
||
async down(queryInterface) { | ||
await Promise.all([ | ||
queryInterface.removeColumn('organizations', 'fileStoreId'), | ||
queryInterface.removeColumn('projectLocations', 'fileId'), | ||
queryInterface.dropTable('fileStore'), | ||
]); | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import stub from './file-store.stub.json'; | ||
|
||
export const MetaMock = { | ||
findAll: () => stub, | ||
findOne: (id) => { | ||
return stub.find((record) => record.id == id); | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
'use strict'; | ||
|
||
/* | ||
We use the SHA256 hash as the unique file ID, | ||
this prevents duplicate files from being uploaded to the same store. | ||
*/ | ||
|
||
import Sequelize from 'sequelize'; | ||
const { Model } = Sequelize; | ||
import { sequelize } from '../../database'; | ||
import { Organization } from '../organizations'; | ||
|
||
import datalayer from '../../datalayer'; | ||
import { encodeHex } from '../../utils/datalayer-utils'; | ||
|
||
import ModelTypes from './file-store.modeltypes.cjs'; | ||
|
||
class FileStore extends Model { | ||
static async addFileToFileStore(SHA256, fileName, base64File) { | ||
const myOrganization = await Organization.getHomeOrg(); | ||
let fileStoreId = myOrganization.fileStoreId; | ||
|
||
if (!fileStoreId) { | ||
fileStoreId = datalayer.createDataLayerStore(); | ||
datalayer.syncDataLayer(myOrganization.orgUid, { fileStoreId }); | ||
Organization.update( | ||
{ fileStoreId }, | ||
{ where: { orgUid: myOrganization.orgUid } }, | ||
); | ||
throw new Error('New File store being created, please try again later.'); | ||
} | ||
|
||
const existingFile = await FileStore.findOne({ | ||
where: { SHA256 }, | ||
attributes: ['SHA256'], | ||
}); | ||
|
||
if (existingFile) { | ||
throw new Error('File Already exists in the filestore'); | ||
} | ||
|
||
datalayer.syncDataLayer(fileStoreId, { | ||
[SHA256]: JSON.stringify({ | ||
name: fileName, | ||
file: base64File, | ||
}), | ||
}); | ||
|
||
FileStore.upsert({ | ||
SHA256, | ||
fileName, | ||
data: base64File, | ||
orgUid: myOrganization.orgUid, | ||
}); | ||
} | ||
|
||
static async getFileStoreList() { | ||
const myOrganization = await Organization.getHomeOrg(); | ||
let fileStoreId = myOrganization.fileStoreId; | ||
|
||
if (!fileStoreId) { | ||
fileStoreId = await datalayer.createDataLayerStore(); | ||
datalayer.syncDataLayer(myOrganization.orgUid, { fileStoreId }); | ||
throw new Error('New File store being created, please try again later.'); | ||
} | ||
|
||
new Promise((resolve, reject) => { | ||
datalayer.getStoreData( | ||
myOrganization.fileStoreId, | ||
(data) => { | ||
resolve(data); | ||
}, | ||
reject, | ||
); | ||
}).then((fileStore) => { | ||
// Just caching this so dont await it, we dont care when it finishes | ||
return Promise.all( | ||
Object.keys(fileStore).map((key) => { | ||
FileStore.upsert({ | ||
SHA256: fileStore[key].SHA256, | ||
fileName: key, | ||
data: fileStore[key].data, | ||
orgUid: myOrganization.orgUid, | ||
}); | ||
}), | ||
); | ||
}); | ||
|
||
return FileStore.findAll({ | ||
attributes: ['SHA256', 'fileName'], | ||
raw: true, | ||
}); | ||
} | ||
|
||
static async deleteFileStorItem(SHA256) { | ||
const myOrganization = await Organization.getHomeOrg(); | ||
let fileStoreId = myOrganization.fileStoreId; | ||
|
||
if (!fileStoreId) { | ||
fileStoreId = await datalayer.createDataLayerStore(); | ||
datalayer.syncDataLayer(myOrganization.orgUid, { fileStoreId }); | ||
throw new Error('New File store being created, please try again later.'); | ||
} | ||
|
||
const changeList = { | ||
action: 'delete', | ||
key: encodeHex(SHA256), | ||
}; | ||
|
||
datalayer.pushChangesWhenStoreIsAvailable(fileStoreId, changeList); | ||
|
||
FileStore.destroy({ where: { SHA256, orgUid: myOrganization.org } }); | ||
} | ||
|
||
static async getFileStoreItem(SHA256) { | ||
const myOrganization = await Organization.getHomeOrg(); | ||
let fileStoreId = myOrganization.fileStoreId; | ||
|
||
if (!fileStoreId) { | ||
fileStoreId = await datalayer.createDataLayerStore(); | ||
datalayer.syncDataLayer(myOrganization.orgUid, { fileStoreId }); | ||
throw new Error('New File store being created, please try again later.'); | ||
} | ||
|
||
const cachedFile = await FileStore.findOne({ | ||
where: { SHA256 }, | ||
raw: true, | ||
}); | ||
|
||
if (cachedFile) { | ||
return cachedFile.data; | ||
} | ||
|
||
const fileStore = await new Promise((resolve, reject) => { | ||
datalayer.getStoreData( | ||
myOrganization.fileStoreId, | ||
(data) => { | ||
resolve(data); | ||
}, | ||
() => reject(), | ||
); | ||
}); | ||
|
||
// Just caching this so dont await it, we dont care when it finishes | ||
FileStore.upsert({ | ||
SHA256, | ||
fileName: fileStore[SHA256].fileName, | ||
data: fileStore[SHA256].data, | ||
}); | ||
|
||
return fileStore[SHA256].data; | ||
} | ||
} | ||
|
||
FileStore.init(ModelTypes, { | ||
sequelize, | ||
modelName: 'fileStore', | ||
freezeTableName: true, | ||
timestamps: false, | ||
createdAt: false, | ||
updatedAt: false, | ||
}); | ||
|
||
export { FileStore }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
const Sequelize = require('sequelize'); | ||
|
||
module.exports = { | ||
// ID is SHA256 so there are no file duplications | ||
SHA256: { | ||
type: Sequelize.STRING, | ||
allowNull: false, | ||
unique: true, | ||
primaryKey: true, | ||
}, | ||
fileName: { | ||
type: Sequelize.STRING, | ||
unique: true, | ||
}, | ||
data: Sequelize.STRING, | ||
orgUid: Sequelize.STRING, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './file-store.model.js'; | ||
export * from './file-store.mock.js'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.