Skip to content

Commit

Permalink
feat: edit organization info
Browse files Browse the repository at this point in the history
  • Loading branch information
frantzarty committed Jun 17, 2022
1 parent 40af1f4 commit 4927e88
Show file tree
Hide file tree
Showing 6 changed files with 327 additions and 239 deletions.
31 changes: 31 additions & 0 deletions src/controllers/organization.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,37 @@ export const findAll = async (req, res) => {
return res.json(await Organization.getOrgsMap());
};

export const editHomeOrg = async (req, res) => {
try {
await assertIfReadOnlyMode();
await assertWalletIsSynced();
await assertHomeOrgExists();

const { name } = req.body;

let icon;

if (_.get(req, 'files.file.data')) {
const buffer = req.files.file.data;
icon = `data:image/png;base64, ${buffer.toString('base64')}`;
} else {
icon = '';
}

Organization.editOrgMeta({ name, icon });

return res.json({
message: 'Home org currently being updated, will be completed soon.',
});
} catch (error) {
console.trace(error);
res.status(400).json({
message: 'Error initiating your organization',
error: error.message,
});
}
};

export const createV2 = async (req, res) => {
try {
await assertIfReadOnlyMode();
Expand Down
333 changes: 184 additions & 149 deletions src/datalayer/writeService.js
Original file line number Diff line number Diff line change
@@ -1,149 +1,184 @@
import _ from 'lodash';

import * as dataLayer from './persistance';
import wallet from './wallet';
import * as simulator from './simulator';
import { encodeHex, decodeHex } from '../utils/datalayer-utils';
import { getConfig } from '../utils/config-loader';
import { logger } from '../config/logger.cjs';

logger.info('climate-warehouse:datalayer:writeService');

const { USE_SIMULATOR } = getConfig().APP;

const createDataLayerStore = async () => {
let storeId;
if (USE_SIMULATOR) {
storeId = await simulator.createDataLayerStore();
} else {
storeId = await dataLayer.createDataLayerStore();

logger.info(
`Created storeId: ${storeId}, waiting for this to be confirmed on the blockchain.`,
);
await waitForStoreToBeConfirmed(storeId);
}

return storeId;
};

const waitForStoreToBeConfirmed = async (storeId, retry = 0) => {
if (retry > 120) {
throw new Error(
`Creating storeId: ${storeId} timed out. Its possible the transaction is stuck.`,
);
}

const storeExistAndIsConfirmed = await dataLayer.getRoot(storeId);

if (!storeExistAndIsConfirmed) {
logger.info(`Still waiting for ${storeId} to confirm`);
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 30000);
});
return waitForStoreToBeConfirmed(storeId, retry + 1);
}
logger.info(`StoreId: ${storeId} has been confirmed. Congrats!`);
};

const syncDataLayer = async (storeId, data, failedCallback) => {
logger.info(`Syncing ${storeId}`);
const changeList = Object.keys(data).map((key) => {
return {
action: 'insert',
key: encodeHex(key),
value: encodeHex(data[key]),
};
});

await pushChangesWhenStoreIsAvailable(storeId, changeList, failedCallback);
};

const retry = (storeId, changeList, failedCallback, retryAttempts) => {
logger.info(`Retrying pushing to store ${storeId}: ${retryAttempts}`);
if (retryAttempts >= 60) {
logger.info(
'Could not push changelist to datalayer after retrying 10 times',
);
failedCallback();
return;
}

setTimeout(async () => {
await pushChangesWhenStoreIsAvailable(
storeId,
changeList,
failedCallback,
retryAttempts + 1,
);
}, 30000);
};

const pushChangesWhenStoreIsAvailable = async (
storeId,
changeList,
failedCallback = _.noop,
retryAttempts = 0,
) => {
if (USE_SIMULATOR) {
return simulator.pushChangeListToDataLayer(storeId, changeList);
} else {
const hasUnconfirmedTransactions =
await wallet.hasUnconfirmedTransactions();

const storeExistAndIsConfirmed = await dataLayer.getRoot(storeId);

if (!hasUnconfirmedTransactions && storeExistAndIsConfirmed) {
logger.info(
`pushing to datalayer ${storeId} ${JSON.stringify(
changeList.map((change) => {
return {
action: change.action,
key: decodeHex(change.key),
value: /{([^*]*)}/.test(decodeHex(change.value))
? JSON.parse(decodeHex(change.value))
: decodeHex(change.value),
};
}),
null,
2,
)}`,
);

const success = await dataLayer.pushChangeListToDataLayer(
storeId,
changeList,
);

if (!success) {
logger.info(
`RPC failed when pushing to store ${storeId}, attempting retry.`,
);
retry(storeId, changeList, failedCallback, retryAttempts);
}
} else {
retry(storeId, changeList, failedCallback, retryAttempts);
}
}
};

const pushDataLayerChangeList = (storeId, changeList, failedCallback) => {
pushChangesWhenStoreIsAvailable(storeId, changeList, failedCallback);
};

const dataLayerAvailable = async () => {
if (USE_SIMULATOR) {
return simulator.dataLayerAvailable();
} else {
return dataLayer.dataLayerAvailable();
}
};

export default {
dataLayerAvailable,
pushDataLayerChangeList,
syncDataLayer,
createDataLayerStore,
};
import _ from 'lodash';

import * as dataLayer from './persistance';
import wallet from './wallet';
import * as simulator from './simulator';
import { encodeHex, decodeHex } from '../utils/datalayer-utils';
import { getConfig } from '../utils/config-loader';
import { logger } from '../config/logger.cjs';
import { Organization } from '../models';

logger.info('climate-warehouse:datalayer:writeService');

const { USE_SIMULATOR } = getConfig().APP;

const createDataLayerStore = async () => {
let storeId;
if (USE_SIMULATOR) {
storeId = await simulator.createDataLayerStore();
} else {
storeId = await dataLayer.createDataLayerStore();

logger.info(
`Created storeId: ${storeId}, waiting for this to be confirmed on the blockchain.`,
);
await waitForStoreToBeConfirmed(storeId);
}

return storeId;
};

const waitForStoreToBeConfirmed = async (storeId, retry = 0) => {
if (retry > 120) {
throw new Error(
`Creating storeId: ${storeId} timed out. Its possible the transaction is stuck.`,
);
}

const storeExistAndIsConfirmed = await dataLayer.getRoot(storeId);

if (!storeExistAndIsConfirmed) {
logger.info(`Still waiting for ${storeId} to confirm`);
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 30000);
});
return waitForStoreToBeConfirmed(storeId, retry + 1);
}
logger.info(`StoreId: ${storeId} has been confirmed. Congrats!`);
};

const syncDataLayer = async (storeId, data, failedCallback) => {
logger.info(`Syncing ${storeId}`);
const changeList = Object.keys(data).map((key) => {
return {
action: 'insert',
key: encodeHex(key),
value: encodeHex(data[key]),
};
});

await pushChangesWhenStoreIsAvailable(storeId, changeList, failedCallback);
};

const upsertDataLayer = async (storeId, data) => {
logger.info(`Syncing ${storeId}`);
const homeOrg = await Organization.getHomeOrg();
let changeList = Object.keys(data).map((key) => {
const change = [];

if (homeOrg[key]) {
change.push({
action: 'delete',
key: encodeHex(key),
});
}

change.push({
action: 'insert',
key: encodeHex(key),
value: encodeHex(data[key]),
});
return change;
});

const finalChangeList = _.uniqBy(
_.sortBy(_.flatten(_.values(changeList)), 'action'),
(v) => [v.action, v.key].join(),
);

console.log('!!!!!', finalChangeList);

await pushChangesWhenStoreIsAvailable(storeId, finalChangeList);
};

const retry = (storeId, changeList, failedCallback, retryAttempts) => {
logger.info(`Retrying pushing to store ${storeId}: ${retryAttempts}`);
if (retryAttempts >= 60) {
logger.info(
'Could not push changelist to datalayer after retrying 10 times',
);
failedCallback();
return;
}

setTimeout(async () => {
await pushChangesWhenStoreIsAvailable(
storeId,
changeList,
failedCallback,
retryAttempts + 1,
);
}, 30000);
};

const pushChangesWhenStoreIsAvailable = async (
storeId,
changeList,
failedCallback = _.noop,
retryAttempts = 0,
) => {
if (USE_SIMULATOR) {
return simulator.pushChangeListToDataLayer(storeId, changeList);
} else {
const hasUnconfirmedTransactions =
await wallet.hasUnconfirmedTransactions();

const storeExistAndIsConfirmed = await dataLayer.getRoot(storeId);

if (!hasUnconfirmedTransactions && storeExistAndIsConfirmed) {
logger.info(
`pushing to datalayer ${storeId} ${JSON.stringify(
changeList.map((change) => {
return {
action: change.action,
key: decodeHex(change.key),
...(change.value && {
value: /{([^*]*)}/.test(decodeHex(change.value))
? JSON.parse(decodeHex(change.value))
: decodeHex(change.value),
}),
};
}),
null,
2,
)}`,
);

const success = await dataLayer.pushChangeListToDataLayer(
storeId,
changeList,
);

if (!success) {
logger.info(
`RPC failed when pushing to store ${storeId}, attempting retry.`,
);
retry(storeId, changeList, failedCallback, retryAttempts);
}
} else {
retry(storeId, changeList, failedCallback, retryAttempts);
}
}
};

const pushDataLayerChangeList = (storeId, changeList, failedCallback) => {
pushChangesWhenStoreIsAvailable(storeId, changeList, failedCallback);
};

const dataLayerAvailable = async () => {
if (USE_SIMULATOR) {
return simulator.dataLayerAvailable();
} else {
return dataLayer.dataLayerAvailable();
}
};

export default {
dataLayerAvailable,
pushDataLayerChangeList,
syncDataLayer,
createDataLayerStore,
upsertDataLayer,
};
16 changes: 16 additions & 0 deletions src/models/organizations/organizations.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,22 @@ class Organization extends Model {
logger.info(error);
}
};

static editOrgMeta = async ({ name, icon }) => {
const myOrganization = await Organization.getHomeOrg();

const payload = {};

if (name) {
payload.name = name;
}

if (icon) {
payload.icon = icon;
}

await datalayer.upsertDataLayer(myOrganization.orgUid, payload);
};
}

Organization.init(ModelTypes, {
Expand Down
Loading

0 comments on commit 4927e88

Please sign in to comment.