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

Limit operation types per linkage #211

Merged
merged 15 commits into from
Nov 6, 2022
2 changes: 1 addition & 1 deletion src/components/add-account.vue
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
*/
async function addAccounts() {
if (!accounts_to_import.value) {
ipcRenderer.send("notify", "No account selected!");
ipcRenderer.send("notify", t(`common.addAccount.none_selected`));
return;
}

Expand Down
10 changes: 5 additions & 5 deletions src/components/balances.vue
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,14 @@
class="step_btn"
@click="loadBalances()"
>
Refresh
{{ t('common.balances.refresh') }}
</ui-button>
<ui-button
v-else-if="!isConnected && !isConnecting"
class="step_btn"
@click="loadBalances()"
>
Reconnect
{{ t('common.balances.reconnect') }}
</ui-button>

<ui-table
Expand All @@ -119,7 +119,7 @@
v-if="balances && !balances.length"
outlined
>
No balances in account
{{ t('common.balances.empty') }}
</ui-card>
<ui-card
v-if="isConnecting"
Expand All @@ -129,15 +129,15 @@
<figure>
<ui-progress indeterminate />
<br>
<figcaption>Connecting to blockchain</figcaption>
<figcaption>{{ t('common.balances.connecting') }}</figcaption>
</figure>
</ui-card>
<ui-card
v-if="!isConnected && !isConnecting"
outlined
style="padding:5px"
>
Couldn't to connect to blockchain
{{ t('common.balances.error') }}
</ui-card>
</div>
</template>
2 changes: 1 addition & 1 deletion src/components/dashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
required
full-bleed
>
Account
{{ t('common.account') }}
</ui-select>
<AccountDetails :account="selectedAccount" />
<Balances :account="selectedAccount" />
Expand Down
51 changes: 48 additions & 3 deletions src/components/popups/linkrequestpopup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import { ref, onMounted, computed } from "vue";
import RendererLogger from "../../lib/RendererLogger";
import {formatChain, formatAccount} from "../../lib/formatter";
import getBlockchainAPI from "../../lib/blockchains/blockchainFactory";
import sha512 from "crypto-js/sha512.js";

import { useI18n } from 'vue-i18n';
const { t } = useI18n({ useScope: 'global' });
Expand Down Expand Up @@ -52,6 +54,35 @@
return t('operations.link.request_fresh', {chain: props.request.chain });
});

let chainOperations = computed(() => {
let types = getBlockchainAPI(props.request.chain).getOperationTypes();
if (!props.request.injectables.length) {
// All operations are required
return types.map(type => `${type.id}: ${type.method.replaceAll("_", " ")}`);
}

let injectChips = [];
for (let i = 0; i < props.request.injectables.length; i++) {
// Subset of operations are required
const currentInjection = props.request.injectables[i]; // id
let foundCurrent = types.find(type => type.id === currentInjection.id);
if (!foundCurrent) {
injectChips = []; // invalid op will nullify link request
break;
} else {
injectChips.push({
text: `${foundCurrent.id}: ` + t(`operations.injected.BTS.${foundCurrent.method}`),
tooltip: t(`operations.injected.BTS.${foundCurrent.method}.tooltip`)
})
}
}
if (!injectChips.length) {
// Avoid rendering warning
return null;
}
return injectChips;
});

/*
* Creating the select items
*/
Expand Down Expand Up @@ -113,6 +144,17 @@
{{ secondText }}
</div>
<br>
<div v-if="chainOperations && chainOperations.length">
<ui-chips id="input-chip-set" type="input" :items="list">
<ui-chip
v-for="item in chainOperations"
:key="sha512(item.text).toString()"
v-tooltip="item.tooltip"
>
{{ item.text }}
</ui-chip>
</ui-chips>
</div>
<div v-if="accountOptions && accountOptions.length > 0">
<select
id="account_select"
Expand All @@ -125,7 +167,7 @@
disabled
value=""
>
Account select
{{ t('operations.link.account_select') }}
</option>
<option
v-for="account in accountOptions"
Expand All @@ -139,10 +181,13 @@
</select>
</div>
<div v-else>
Requested account not present in this Beet wallet.
{{ t('operations.link.account_missing') }}
</div>
<br>
<div v-if="chosenAccount == -1">
<div v-if="chosenAccount == -1 || !chainOperations">
<ui-alert v-if="!chainOperations" state="error">
{{ t('operations.link.invalid_operations') }}
</ui-alert>
<ui-button
style="margin-right:5px"
disabled
Expand Down
6 changes: 3 additions & 3 deletions src/components/popups/relinkrequestpopup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@
v-else
style="padding:5px"
>
<div>
Error showing prompt
</div>
<ui-alert v-if="!chainOperations" state="error">
{{ t('operations.relink.error') }}
</ui-alert>
<br>
<ui-button
raised
Expand Down
2 changes: 1 addition & 1 deletion src/components/popups/transactionrequestpopup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@
class="text-left custom-content"
>
<pre>
Loading transaction details from blockchain, please wait.
{{ t('operations.rawsig.loading') }}
</pre>
</div>

Expand Down
6 changes: 3 additions & 3 deletions src/components/popups/transferrequestpopup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -159,17 +159,17 @@
<ui-list>
<ui-item key="Recipient">
<ui-item-text-content>
Recipient: {{ to }} ({{ target }})
{{ t("operations.transfer.to") }}: {{ to }} ({{ target }})
</ui-item-text-content>
</ui-item>
<ui-item key="Amount">
<ui-item-text-content>
Amount: {{ toSend }} ({{ asset_id }})
{{ t("operations.transfer.amount") }}: {{ toSend }} ({{ asset_id }})
</ui-item-text-content>
</ui-item>
<ui-item v-if="memo" key="Memo">
<ui-item-text-content>
Memo: {{ memo }}
{{ t("operations.transfer.memo") }}: {{ memo }}
</ui-item-text-content>
</ui-item>
<ui-item
Expand Down
6 changes: 3 additions & 3 deletions src/components/restore.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
passError.value = true;
store.dispatch(
"WalletStore/notifyUser",
{notify: "request", message: "Account recovery error!"}
{notify: "request", message: t('common.apiUtils.restore.decryptError')}
);
return;
}
Expand All @@ -98,7 +98,7 @@
passError.value = true;
store.dispatch(
"WalletStore/notifyUser",
{notify: "request", message: "Invalid recovered wallet password"}
{notify: "request", message: t('common.apiUtils.restore.invalidPassword')}
);
return;
}
Expand All @@ -110,7 +110,7 @@
console.log("A wallet with the same name already exists, aborting wallet restoration");
store.dispatch(
"WalletStore/notifyUser",
{notify: "request", message: "A wallet with the same name already exists, aborting wallet restoration"}
{notify: "request", message: t('common.apiUtils.restore.duplicate')}
);
return;
}
Expand Down
24 changes: 20 additions & 4 deletions src/components/settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,40 @@

watchEffect(() => {
if (dapps.value && dapps.value.length) {
let types = getBlockchainAPI(props.request.chain).getOperationTypes();

tableData.value = {
data: dapps.value.map(dapp => {
return {
appName: dapp.appName,
origin: dapp.origin,
displayString: getDisplayString(dapp.account_id, dapp.chain),
chain: dapp.chain,
actions: dapp.id
actions: dapp.id,
injectables: <ui-chips id="input-chip-set" type="input" items="list">
{
dapp.injectables.map(op => {
let current = types.find(type => type.id === op);
return <ui-chip
key={sha512(current.method).toString()}
v-tooltip={t(`operations.injected.BTS.${current.method}.tooltip`)}
>
{current.id}: {t(`operations.injected.BTS.${current.method}`)}
</ui-chip>
})
}
</ui-chips>
}
}),
thead: [
t('common.appname_lbl'),
t('common.origin_lbl'),
t('common.account_lbl'),
t('common.chain_lbl'),
t('common.actions_lbl')
t('common.actions_lbl'),
t('common.operations_lbl')
],
tbody: ['appName', 'origin', 'displayString', 'chain', {slot: 'actions'}]
tbody: ['appName', 'origin', 'displayString', 'chain', {slot: 'actions'}, 'injectables']
};
}
});
Expand Down Expand Up @@ -153,7 +169,7 @@
outlined
class="step_btn"
>
Exit settings menu
{{ t('common.settings.exit') }}
</ui-button>
</router-link>
</div>
Expand Down
7 changes: 5 additions & 2 deletions src/components/start.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@
})
.catch(() => {
passincorrect.value = "is-invalid";
ipcRenderer.send("notify", 'An attempt to unlock the Beet wallet was made with an invalid password.');
ipcRenderer.send(
"notify",
t('common.start.invalid_password')
);
});
}
</script>
Expand Down Expand Up @@ -106,7 +109,7 @@
full-bleed
@change="passincorrect=''"
>
Beet wallet name
{{ t('common.start.wallet_name') }}
</ui-select>
</section>
<input
Expand Down
38 changes: 32 additions & 6 deletions src/lib/BeetServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ const linkHandler = async (req) => {
origin: req.origin,
account_id: userResponse.result.id,
chain: userResponse.result.chain,
injectables: req.injectables ?? [],
secret: secret,
next_hash: req.payload.next_hash
});
Expand Down Expand Up @@ -235,7 +236,7 @@ export default class BeetServer {

let msg = JSON.parse(decryptedValue);
if (!Object.keys(Actions).map(key => Actions[key]).includes(msg.method)) {
console.log("Unsupported request type rejected");
console.log("Unauthorized use of injected operation");
socket.emit("api", {id: data.id, error: true, payload: {code: 3, message: "Request type not supported."}});
return;
}
Expand All @@ -254,11 +255,6 @@ export default class BeetServer {
payload: msg
};

store.dispatch('OriginStore/newRequest', {
identityhash: apiobj.payload.identityhash,
next_hash: apiobj.payload.next_hash
});

let blockchainActions = [
Actions.SIGN_MESSAGE,
Actions.SIGN_NFT,
Expand All @@ -280,6 +276,36 @@ export default class BeetServer {
}
}

if (blockchain && blockchain.getOperationTypes().length) {
// Check injected operation types are allowed
let app = store.getters['OriginStore/getBeetApp'](req);
if (!app || (!req.payload.origin == app.origin && !req.payload.appName == app.appName)) {
socket.emit("api", {id: data.id, error: true, payload: {code: 3, message: "Request format issue."}});
return;
}

// request.payload.params
let tr = blockchain._parseTransactionBuilder(msg.params);
let authorizedUse = true;
for (let i = 0; i < tr.operations.length; i++) {
let operation = tr.operations[i];
if (!app.injectables.includes(operation[0])) {
authorizedUse = false;
break;
}
}

if (!authorizedUse) {
socket.emit("api", {id: data.id, error: true, payload: {code: 3, message: "Unauthorized blockchain operations detected."}});
return;
}
}

store.dispatch('OriginStore/newRequest', {
identityhash: apiobj.payload.identityhash,
next_hash: apiobj.payload.next_hash
});

let status;
try {
if (apiobj.type === Actions.GET_ACCOUNT) {
Expand Down
Loading