Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add import organization api #304

Merged
merged 1 commit into from
Feb 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/controllers/organization.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,23 @@ export const create = async (req, res) => {
};

// eslint-disable-next-line
export const importOrg = async (req, res) => {};
export const importOrg = async (req, res) => {
const { orgUid, ip, port } = req.body;
try {
res.json({
message:
'Importing and subscribing organization this can take a few mins.',
});

return Organization.importOrganization(orgUid, ip, port);
} catch (error) {
console.trace(error);
res.status(400).json({
message: 'Error importing organization',
error: error.message,
});
}
};

export const subscribeToOrganization = async (req, res) => {
try {
Expand Down
42 changes: 38 additions & 4 deletions src/datalayer/persistance.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ export const getRoot = async (storeId) => {

try {
const data = JSON.parse(response);
console.log(data);
if (data.status === 2) {
console.log(`Root for ${storeId}`, data);
if (data.status === 2 && !data.hash.includes('0x00000000000')) {
return data;
}

Expand All @@ -138,11 +138,14 @@ export const getStoreData = async (storeId) => {
const data = JSON.parse(response);

if (data.success) {
console.log('Downloaded Data', data);
return data;
}

console.log('&&&&', data);
}

return new Error('Error getting datalayer store data');
return false;
};

export const dataLayerAvailable = async () => {
Expand All @@ -158,7 +161,7 @@ export const dataLayerAvailable = async () => {

const data = JSON.parse(response);

if (Object.keys(data).includes('success')) {
if (Object.keys(data).includes('success') && data.success) {
return true;
}

Expand All @@ -167,3 +170,34 @@ export const dataLayerAvailable = async () => {
return false;
}
};

export const subscribeToStoreOnDataLayer = async (storeId, ip, port) => {
const options = {
url: `${rpcUrl}/subscribe`,
body: JSON.stringify({
id: storeId,
ip,
port,
}),
};

console.log('Subscribing to: ', storeId, ip, port);

try {
const response = await request(
Object.assign({}, getBaseOptions(), options),
);

const data = JSON.parse(response);

if (Object.keys(data).includes('success') && data.success) {
console.log('Successfully Subscribed: ', storeId, ip, port);
return data;
}

return false;
} catch (error) {
console.log('Error Subscribing: ', error);
return false;
}
};
2 changes: 1 addition & 1 deletion src/datalayer/simulator.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,4 @@ export const dataLayerAvailable = async () => {
};

// eslint-disable-next-line
export const subscribeToStore = async (storeId) => {};
export const subscribeToStoreOnDataLayer = async (storeId) => {};
66 changes: 62 additions & 4 deletions src/datalayer/syncService.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import _ from 'lodash';

import logUpdate from 'log-update';

import { decodeHex } from '../utils/datalayer-utils';
import { decodeHex, decodeDataLayerResponse } from '../utils/datalayer-utils';
import { Organization, Staging, ModelKeys } from '../models';

import * as dataLayer from './persistance';
Expand Down Expand Up @@ -115,8 +115,6 @@ export const dataLayerWasUpdated = async () => {
rootResponse = await dataLayer.getRoots(subscribedOrgIds);
}

console.log(rootResponse);

if (!rootResponse.success) {
return [];
}
Expand All @@ -127,7 +125,6 @@ export const dataLayerWasUpdated = async () => {
);

if (org) {
console.log(rootHash);
// store has been updated if its confirmed and the hash has changed
return rootHash.status === 2 && org.registryHash != rootHash.hash;
}
Expand Down Expand Up @@ -155,3 +152,64 @@ export const dataLayerWasUpdated = async () => {

return updatedStoreIds;
};

export const subscribeToStoreOnDataLayer = async (storeId, ip, port) => {
if (process.env.USE_SIMULATOR === 'true') {
return simulator.subscribeToStoreOnDataLayer(storeId, ip, port);
} else {
return dataLayer.subscribeToStoreOnDataLayer(storeId, ip, port);
}
};

export const getSubscribedStoreData = async (
storeId,
ip,
port,
alreadySubscribed = false,
retry = 0,
) => {
if (retry > 30) {
throw new Error('Max retrys exceeded, Can not subscribe to organization');
}

if (!alreadySubscribed) {
const response = await subscribeToStoreOnDataLayer(storeId, ip, port);
if (!response.success) {
console.log(`Retrying...`, retry + 1);
console.log('...');
await new Promise((resolve) => setTimeout(() => resolve(), 30000));
return getSubscribedStoreData(storeId, ip, port, false, retry + 1);
}
}

if (process.env.USE_SIMULATOR !== 'true') {
const storeExistAndIsConfirmed = await dataLayer.getRoot(storeId);
if (!storeExistAndIsConfirmed) {
console.log(`Retrying...`, retry + 1);
console.log('...');
await new Promise((resolve) => setTimeout(() => resolve(), 30000));
return getSubscribedStoreData(storeId, ip, port, true, retry + 1);
}
}

let encodedData;
if (process.env.USE_SIMULATOR === 'true') {
encodedData = await simulator.getStoreData(storeId);
} else {
encodedData = await dataLayer.getStoreData(storeId);
}

if (!encodedData) {
console.log(`Retrying...`, retry + 1);
console.log('...');
await new Promise((resolve) => setTimeout(() => resolve(), 30000));
return getSubscribedStoreData(storeId, ip, port, true, retry + 1);
}

const decodedData = decodeDataLayerResponse(encodedData);

return decodedData.reduce((obj, current) => {
obj[current.key] = current.value;
return obj;
}, {});
};
8 changes: 0 additions & 8 deletions src/datalayer/writeService.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,6 @@ export const pushDataLayerChangeList = (storeId, changeList) => {
pushChangesWhenStoreIsAvailable(storeId, changeList);
};

export const subscribeToStore = async (storeId) => {
if (process.env.USE_SIMULATOR === 'true') {
return simulator.subscribeToStore(storeId);
} else {
return dataLayer.subscribeToStore(storeId);
}
};

export const dataLayerAvailable = async () => {
if (process.env.USE_SIMULATOR === 'true') {
return simulator.dataLayerAvailable();
Expand Down
53 changes: 49 additions & 4 deletions src/models/organizations/organizations.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
import Sequelize from 'sequelize';
const { Model } = Sequelize;
import { sequelize } from '../database';
import { createDataLayerStore, syncDataLayer } from '../../datalayer';
import {
createDataLayerStore,
syncDataLayer,
subscribeToStoreOnDataLayer,
getSubscribedStoreData,
} from '../../datalayer';

import ModelTypes from './organizations.modeltypes.cjs';

Expand Down Expand Up @@ -78,8 +83,48 @@ class Organization extends Model {
};

// eslint-disable-next-line
static importHomeOrganization = (orgUid) => {
throw new Error('Not implemented yet');
static importOrganization = async (orgUid, ip, port) => {
const orgData = await getSubscribedStoreData(orgUid, ip, port);

if (!orgData.registryId) {
throw new Error(
'Currupted organization, no registryId on the datalayer, can not import',
);
}

console.log('IMPORTING REGISTRY: ', orgData.registryId);

const registryData = await getSubscribedStoreData(
orgData.registryId,
ip,
port,
);

if (!registryData.v1) {
throw new Error('Organization has no registry, can not import');
}

console.log('IMPORTING REGISTRY V1: ', registryData.v1);

await subscribeToStoreOnDataLayer(registryData.v1, ip, port);

console.log({
orgUid,
name: orgData.name,
icon: orgData.icon,
registryId: registryData.v1,
subscribed: true,
isHome: false,
});

await Organization.upsert({
orgUid,
name: orgData.name,
icon: orgData.icon,
registryId: registryData.v1,
subscribed: true,
isHome: false,
});
};

// eslint-disable-next-line
Expand All @@ -88,7 +133,7 @@ class Organization extends Model {
if (exists) {
await Organization.update({ subscribed: true }, { orgUid });
} else {
Organization.importHomeOrganization(orgUid);
Organization.importOrganization(orgUid);
}
};

Expand Down
1 change: 1 addition & 0 deletions src/models/organizations/organizations.modeltypes.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
type: Sequelize.STRING,
unique: true,
},
orgHash: Sequelize.STRING,
name: Sequelize.STRING,
icon: Sequelize.STRING,
registryId: Sequelize.STRING,
Expand Down
14 changes: 7 additions & 7 deletions src/models/organizations/organizations.stub.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
[
{
"orgUid": "78b472ff171a20a9de44555d8df2dc1d4c44bae5f700453a1e59ea6b2609dc5c",
"orgUid": "a807e453-6524-49df-a32d-785e56cf5600",
"name": "My Org",
"registryId": "c1c017b595356361c09f9d2f7720c7da637548191764c5d6df547ddd25144d58",
"registryId": "9144c974e146920088514534c89371dc269d1b894a2c7f6cedeb80b804c6cd02",
"icon": "https://climate-warehouse.s3.us-west-2.amazonaws.com/public/orgs/me.svg",
"subscribed": false,
"isHome": false
"subscribed": true,
"isHome": true
},
{
"orgUid": "ca1e1619-d073-4283-bdbc-4ad58838f727",
"name": "Earl Registrt",
"name": "Earl Registry",
"registryId": "047b74ea567f7591f463f29dcec4cab1e760ef181c006fb3865a3e20ca6144aa",
"icon": "https://climate-warehouse.s3.us-west-2.amazonaws.com/public/orgs/austria.svg",
"subscribed": true,
"subscribed": false,
"isHome": false
},
{
"orgUid": "26462fbf4a10175dbc6945dd3fda35e05da845532f585d79097e06d77ef7165e",
"name": "Kyles Org Registry",
"registryId": "eb9f9440f11f2705dd97da824f6f27079cbde3ad4ff4252539f17c8f0c08a4f9",
"icon": "https://climate-warehouse.s3.us-west-2.amazonaws.com/public/orgs/denmark.svg",
"subscribed": true,
"subscribed": false,
"isHome": false
}
]
7 changes: 7 additions & 0 deletions src/utils/datalayer-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@ export const encodeHex = (str) => {
export const decodeHex = (str) => {
return Buffer.from(str.replace('0x', ''), 'hex').toString();
};

export const decodeDataLayerResponse = (data) => {
return data.keys_values.map((item) => ({
key: decodeHex(item.key),
value: decodeHex(item.value),
}));
};
5 changes: 4 additions & 1 deletion tests/resources/projects.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('Project Resource CRUD', function () {
it('gets all the projects available', async function () {
// no query params
const projects = await testFixtures.getProjectByQuery();
expect(projects.length).to.equal(8);
expect(projects.length).to.equal(11);
});

it('gets all the projects filtered by orgUid', async function () {
Expand All @@ -38,6 +38,7 @@ describe('Project Resource CRUD', function () {
orgUid: 'a807e453-6524-49df-a32d-785e56cf560e',
search: 'City of Arcata',
});

expect(projects.length).to.equal(1);
});

Expand All @@ -53,6 +54,8 @@ describe('Project Resource CRUD', function () {
page: 2,
limit: 3,
});

console.log(projectsPage2);
expect(projectsPage2.data.length).to.equal(3);
expect(projectsPage1.data).to.not.deep.equal(projectsPage2.data);

Expand Down
2 changes: 2 additions & 0 deletions tests/test-fixtures/project-fixtures.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ export const getProject = async (warehouseProjectId) => {
export const getProjectByQuery = async (query = {}) => {
const result = await supertest(app).get('/v1/projects').query(query);
// expect(result.body).to.be.an('array');
expect('!!!!!', result);
expect(result.statusCode).to.equal(200);

return result.body;
};

Expand Down