Skip to content

Commit

Permalink
Merge pull request #206 from positivecrash/main
Browse files Browse the repository at this point in the history
hack jb lab + demo pages
  • Loading branch information
positivecrash authored Jun 7, 2024
2 parents 38d31c7 + 81cf200 commit 1690553
Show file tree
Hide file tree
Showing 14 changed files with 321 additions and 4 deletions.
4 changes: 2 additions & 2 deletions src/assets/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ u {
}

section {
margin-bottom: calc(var(--gap) * 3);
margin-top: calc(var(--gap) * 3);
margin-bottom: calc(var(--gap) * 2);
margin-top: calc(var(--gap) * 2);
}

section:first-child { margin-top: 0; }
Expand Down
Binary file added src/assets/images/demoapps/johnnyb-lab-cover.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/tboticon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/components/Header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

<nav id="nav" class="nav header__section">
<g-link class="nav__link" :class="{'active': $route.path.includes('learn')}" to="/learn/">{{$t('Learn')}}</g-link>
<g-link class="nav__link" :class="{'active': $route.path.includes('demoapps')}" to="/demoapps/">Demo Apps</g-link>
<!-- <g-link class="nav__link" :class="{'active': $route.path.includes('playground')}" to="/playground/">{{$ts('Playground')}}</g-link> -->
<!-- <g-link class="nav__link" :class="{'active': $route.path.includes('certificates')}" to="/certificates/">{{$ts('Blockchain certificate')}}</g-link> -->
<g-link class="nav__link" to="https://robonomics.network/">{{$t('Robonomics website')}}</g-link>
Expand Down Expand Up @@ -136,7 +137,6 @@ export default {
.header a:not(:last-child) {
margin-right: var(--gap);
margin-left: var(--gap);
}
.header a:hover {
Expand Down
7 changes: 6 additions & 1 deletion src/data/locales/routes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,9 @@
- path: '/learn/'
component: './src/pages/Learn.vue'
typename: 'page'

- path: '/demoapps/'
component: './src/pages/demoapps/Index.vue'
typename: 'page'
- path: '/demoapps/johnnyb-lab/'
component: './src/pages/demoapps/johnnyb-lab.vue'
typename: 'page'
3 changes: 3 additions & 0 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import Vuex from 'vuex'
import 'prismjs'

// import robonomics from "./plugins/robonomics";

// adding languages for code highlight
import 'prismjs/components/prism-json';
import 'prismjs/components/prism-bash';
Expand Down Expand Up @@ -89,6 +91,7 @@ import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'

export default function (Vue, { router, head, isClient, appOptions }) {
Vue.use(Vuex);
// Vue.use(robonomics, { endpoint: "wss://kusama.rpc.robonomics.network/" });

// Set default layout as a global component
Vue.component('Layout', DefaultLayout)
Expand Down
31 changes: 31 additions & 0 deletions src/pages/demoapps/Index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<template>
<Layout>
<section class="container__narrow">
<h1>{{$t('Demo academic apps')}}</h1>
<p class="pagedesc">{{$t('Here are some demonstrational applications for academic needs. Some of them can be active, some of them not.')}}</p>
</section>

<section class="container__narrow">
<g-link to="/demoapps/johnnyb-lab/" class="cover">
<g-image src="@/assets/images/demoapps/johnnyb-lab-cover.jpg" aria-hidden="true" alt="Hack Johnny's lab demo"/>
</g-link>
<g-link to="/demoapps/johnnyb-lab/" class="title">Hack Johnny's lab</g-link>
</section>
</Layout>
</template>

<style scoped>
.cover, .cover img {
display: block;
}
.cover img {
max-width: 100%;
}
.title {
font-weight: 700;
margin-top: 10px;
display: block;
}
</style>
56 changes: 56 additions & 0 deletions src/pages/demoapps/johnnyb-lab.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<template>
<Layout>
<section class="container__narrow">
<h1>{{$t("Hack Johnny's lab")}}</h1>
</section>

<section class="container__narrow">
<div class="pagedesc">
<p>{{$t("Johny's crypto lab is a cutting-edge hub filled with all sorts of smart gadgets, including a TurtleBot 4 robot that is known as a base for an iRobot vacuum. But imagine the thrill—and the risk—if someone managed to hack into the robot's camera. Ready to dive into the world of cybersecurity and test your hacking skills? See what you can uncover!")}} <a href="https://robonomics.network/blog/robonomics-school-2024-hack-johnny-lab/" target="_blank">{{$t("Rules of the game")}}</a></p>
</div>
</section>

<section class="container__mid">
<iframe id="appframe" src="https://johnnyb-lab.robonomics.academy" sandbox="allow-forms allow-scripts allow-cross-origin" referrerpolicy="cross-origin" scrolling="no" :onload="resizeIframe()" />
</section>
</Layout>
</template>

<script>
export default {
// components: {
// MetaInfo: () => import('~/components/MetaInfo.vue')
// },
methods: {
resizeIframe() {
const iframe = document.getElementById("appframe");
if(iframe) {
console.log('height', iframe.contentWindow.document.body.scrollHeight);
iframe.style.height = iframe.contentWindow.document.body.scrollHeight + 'px';
}
}
},
mounted() {
window.addEventListener('resize', this.resizeIframe);
},
}
</script>

<style scoped>
.pagedesc {
font-weight: 700;
font-size: 0.9em;
}
iframe {
width: 100%;
height: 1100px;
border: 0;
}
</style>
103 changes: 103 additions & 0 deletions src/robonomics-interface/encryptor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { u8aConcat, u8aToU8a } from "@polkadot/util";
import {
ed25519PairFromSeed,
encodeAddress,
mnemonicToMiniSecret,
randomAsU8a
} from "@polkadot/util-crypto";
import ed2curve from "ed2curve";
import nacl from "tweetnacl";

function naclOpen(sealed, nonce, senderBoxPublic, receiverBoxSecret) {
return (
nacl.box.open(sealed, nonce, senderBoxPublic, receiverBoxSecret) || null
);
}
function naclSeal(
message,
senderBoxSecret,
receiverBoxPublic,
nonce = randomAsU8a(24)
) {
return {
nonce,
sealed: nacl.box(message, nonce, receiverBoxPublic, senderBoxSecret)
};
}
function convertSecretKeyToCurve25519(secretKey) {
return ed2curve.convertSecretKey(secretKey);
}
function convertPublicKeyToCurve25519(publicKey) {
return ed2curve.convertPublicKey(publicKey);
}
export function decryptMessage(
encryptedMessageWithNonce,
senderPublicKey,
secretKey
) {
const messageU8a = u8aToU8a(encryptedMessageWithNonce);
return naclOpen(
messageU8a.slice(24, messageU8a.length),
messageU8a.slice(0, 24),
convertPublicKeyToCurve25519(u8aToU8a(senderPublicKey)),
convertSecretKeyToCurve25519(secretKey)
);
}
export function encryptMessage(
message,
recipientPublicKey,
secretKey,
nonceIn
) {
const { nonce, sealed } = naclSeal(
u8aToU8a(message),
convertSecretKeyToCurve25519(secretKey),
convertPublicKeyToCurve25519(u8aToU8a(recipientPublicKey)),
nonceIn
);
return u8aConcat(nonce, sealed);
}
export function createPair(mnemonic) {
const seed = mnemonicToMiniSecret(mnemonic);
const pair = ed25519PairFromSeed(seed);
return pair;
}
export function encryptor(pair) {
return {
pair,
address: encodeAddress(pair.publicKey, 32),
encodeAddress: (ss58Format = 32) => {
return encodeAddress(pair.publicKey, ss58Format);
},
decryptMessage: (encryptedMessageWithNonce, senderPublicKey) => {
return decryptMessage(
encryptedMessageWithNonce,
senderPublicKey,
pair.secretKey
);
},
encryptMessage: (message, recipientPublicKey, nonce) => {
return encryptMessage(message, recipientPublicKey, pair.secretKey, nonce);
}
};
}
// export function encryptor(mnemonic) {
// const pair = createPair(mnemonic);
// return {
// pair,
// address: encodeAddress(pair.publicKey, 32),
// encodeAddress: (ss58Format = 32) => {
// return encodeAddress(pair.publicKey, ss58Format);
// },
// decryptMessage: (encryptedMessageWithNonce, senderPublicKey) => {
// return decryptMessage(
// encryptedMessageWithNonce,
// senderPublicKey,
// pair.secretKey
// );
// },
// encryptMessage: (message, recipientPublicKey, nonce) => {
// return encryptMessage(message, recipientPublicKey, pair.secretKey, nonce);
// }
// };
// }
19 changes: 19 additions & 0 deletions src/robonomics-interface/robonomics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Keyring } from "@polkadot/keyring";
import { AccountManager, Robonomics } from "robonomics-interface";
import { reactive, ref, toRaw } from "vue";

export default {
install: async (app, params) => {
const isReady = ref(false);
const instance = reactive({ value: undefined });
app.provide("RobonomicsProvider", {
isReady,
instance
});
instance.value = await Robonomics.createInstance(params);
toRaw(instance).value.setAccountManager(
new AccountManager(new Keyring({ type: "ed25519" }))
);
isReady.value = true;
}
};
54 changes: 54 additions & 0 deletions src/robonomics-interface/tools.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { hexToU8a, u8aToString } from "@polkadot/util";
import { decodeAddress } from "@polkadot/util-crypto";
import { createPair, encryptor } from "./encryptor";

const getLastIndex = async (robonomics, address) => {
const id = await robonomics.datalog.getLastId(address);
return id.id;
};
export const getLastDatalog = async (robonomics, address) => {
const lastIndex = await getLastIndex(robonomics, address);
if (lastIndex !== null && lastIndex >= 0) {
const last = await robonomics.datalog.readByIndex(address, lastIndex);
return { timestamp: last[0].toNumber(), cid: u8aToString(last[1]) };
}
return false;
};
export const decryptMsg = (encryptedMsg, account, controller) => {
try {
const seed = account.decryptMessage(
hexToU8a(encryptedMsg.encrypted_keys[account.address]),
decodeAddress(controller)
);
const admin = encryptor(createPair(u8aToString(seed)));
const data = admin.decryptMessage(
hexToU8a(encryptedMsg.data),
decodeAddress(controller)
);
return data;
} catch (error) {
console.log(error.message);
}
return false;
};
const fetchTimeout = (url, ms, { signal, ...options } = {}) => {
const controller = new AbortController();
const promise = fetch(url, { signal: controller.signal, ...options });
if (signal) signal.addEventListener("abort", () => controller.abort());
const timeout = setTimeout(() => controller.abort(), ms);
return promise.finally(() => clearTimeout(timeout));
};
export const getData = async (
robonomics,
account,
gateway = "https://ipfs.io/ipfs/"
) => {
const result = await getLastDatalog(robonomics, account);
const response = await fetchTimeout(`${gateway}${result.cid}`, 30000);
if (response.ok) {
return await response.json();
} else {
console.log("Ошибка HTTP: " + response.status);
}
return false;
};
40 changes: 40 additions & 0 deletions src/robonomics-interface/useDevices.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { validateAddress } from "@polkadot/util-crypto";
import { ref, watch } from "vue";
import { useRobonomics } from "./useRobonomics";

export const useDevices = (initialOwner = null) => {
const robonomics = useRobonomics();
const owner = ref(initialOwner);
const devices = ref([]);

const loadDevices = async () => {
if (robonomics.value && owner.value) {
try {
validateAddress(owner.value);
const result = await robonomics.value.rws.getDevices(owner.value);
devices.value = result.map(item => {
return item.toHuman();
});
return;
} catch (error) {
console.log(error);
}
}
devices.value = [];
};
watch(
owner,
async () => {
await loadDevices();
},
{
immediate: true
}
);

return {
owner,
devices,
loadDevices
};
};
6 changes: 6 additions & 0 deletions src/robonomics-interface/useRobonomics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { inject } from "vue";

export function useRobonomics() {
const { instance } = inject("RobonomicsProvider");
return instance;
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 1690553

Please sign in to comment.