Skip to content

Commit

Permalink
Merge pull request #29 from stc-community/feat-auth
Browse files Browse the repository at this point in the history
Feat: multi user account
  • Loading branch information
rovast authored Jul 25, 2023
2 parents f4b3d8e + d8373b3 commit 0c6e93b
Show file tree
Hide file tree
Showing 14 changed files with 621 additions and 39 deletions.
18 changes: 18 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,23 @@
<div class="loader"></div>
</div>
<script type="module" src="/src/main.ts"></script>
<dialog id="metamask_required" class="modal">
<form method="dialog" class="modal-box">
<h3 class="font-bold text-lg">Hey,</h3>
<p class="py-4">
We use MetaMask to connect blockchain, please install it first
</p>
<div class="modal-action">
<!-- if there is a button in form, it will close the modal -->
<a
class="btn btn-outline btn-primary"
href="https://metamask.io/"
target="__blank"
>Go and Install</a
>
<button class="btn">Close</button>
</div>
</form>
</dialog>
</body>
</html>
5 changes: 5 additions & 0 deletions locales/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,8 @@ tips:
description: We use MetaMask to connect blockchain, please install it first
btn1: Go and Install
btn2: Close Modal
user:
"modal title": Join CloudX3
"modal description": Once you click on "Join". Firstly you need to sign a message for securiting messages with server. Then the platform will generate user information for you, which will be used for subsequent resource creation and management.
"join now": Join Now
cancelSign: Please sign the message for securiting messages between your client and server
5 changes: 5 additions & 0 deletions locales/zh-CN.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,8 @@ tips:
description: 我们使用 MetaMask 来链接区块链,请先安装 MetaMask
btn1: 去安装
btn2: 关闭弹窗
user:
"modal title": 加入 CloudX3
"modal description": 点击加入 CloudX3 后,首先您需要进行签名用于和服务器建立安全通信通道,其次平台会为你生成用户信息,用于后续的资源创建和管理
"join now": 现在加入
cancelSign: 请完成签名,用于和服务器建立安全通信通道
3 changes: 1 addition & 2 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import MonitorModal from "./components/Modal/monitor-modal.vue";
import newFuseRule from "./components/Modal/new-fuse-rule.vue";
import newRateLimitRule from "./components/Modal/new-rate-limit-rule.vue";
import ServiceMonitorModal from "./components/Modal/service-monitor-modal.vue";
import MetamaskModal from "./components/Modal/metamask-modal.vue";
// import MetamaskModal from "./components/Modal/metamask-modal.vue";
defineOptions({
name: "app"
Expand Down Expand Up @@ -49,5 +49,4 @@ onBeforeMount(async () => {
<newFuseRule />
<newRateLimitRule />
<ServiceMonitorModal />
<MetamaskModal />
</template>
50 changes: 50 additions & 0 deletions src/components/Modal/account.bak.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<script setup lang="ts">
import { useAccountStore } from "@/store/modules/account";
import { ref } from "vue";
import { useLang } from "@/hooks/useLang";
const { t } = useLang();
defineOptions({
name: "account"
});
const privateKey = ref("");
const accountStore = useAccountStore();
const handleSubmit = () => {
const err = accountStore.savePrivateKey(privateKey.value);
if (err) {
window.alert(err);
} else {
window.location.reload();
}
};
</script>
<template>
<!-- Put this part before </body> tag -->
<input type="checkbox" id="key-modal" class="modal-toggle" />
<div class="modal backdrop-blur-sm">
<div class="modal-box w-11/12 max-w-xl relative">
<label
for="key-modal"
class="btn btn-sm btn-circle absolute right-2 top-2"
>✕</label
>

<h3 class="font-bold text-lg">{{ t("common.input private key") }}</h3>
<p class="py-4">
<input
v-model="privateKey"
type="text"
:placeholder="t('common.input private key here')"
class="input input-bordered input-primary w-full"
/>
</p>
<div class="modal-action">
<label for="key-modal" class="btn btn-primary" @click="handleSubmit"
>{{ t("common.yay") }}!</label
>
</div>
</div>
</div>
</template>
72 changes: 50 additions & 22 deletions src/components/Modal/account.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,52 @@
<script setup lang="ts">
import { useAccountStore } from "@/store/modules/account";
import { ref } from "vue";
import { useLang } from "@/hooks/useLang";
const { t } = useLang();
defineOptions({
name: "account"
});
import { getNewNostrPrivateKey } from "@/utils/shared";
import { getPublicKey } from "nostr-tools";
import { getUserHubContract } from "@/utils/contract/user-hub";
import { handleEtherError, encrypt } from "@/utils/shared";
import { signMessage, getWalletAddres } from "@/utils/contract/web3";
import { decrypt } from "@/utils/shared";
const privateKey = ref("");
const accountStore = useAccountStore();
const loading = ref(false);
const handleSubmit = async () => {
privateKey.value = getNewNostrPrivateKey();
const publicKey = getPublicKey(privateKey.value);
const contract = await getUserHubContract();
let encryptKey;
try {
loading.value = true;
encryptKey = await signMessage("CloudX3");
} catch (e) {
window.alert(t("user.cancelSign"));
loading.value = false;
return;
}
try {
loading.value = true;
const nostrEncryptKey = encrypt(privateKey.value, encryptKey);
console.log(decrypt(nostrEncryptKey, encryptKey));
console.log(
"用户信息\r\n钱包地址:%s\r\n签名结果:%s\r\nNostr公钥:%s\r\nNostr明文私钥:%s\r\nNostr加密私钥:%s",
await getWalletAddres(),
encryptKey,
publicKey,
privateKey.value,
nostrEncryptKey
);
const transaction = await contract.registerUser(publicKey, nostrEncryptKey);
const handleSubmit = () => {
const err = accountStore.savePrivateKey(privateKey.value);
if (err) {
window.alert(err);
} else {
await transaction.wait();
window.location.reload();
} catch (e) {
loading.value = false;
handleEtherError(e);
}
};
</script>
Expand All @@ -31,19 +61,17 @@ const handleSubmit = () => {
>✕</label
>

<h3 class="font-bold text-lg">{{ t("common.input private key") }}</h3>
<p class="py-4">
<input
v-model="privateKey"
type="text"
:placeholder="t('common.input private key here')"
class="input input-bordered input-primary w-full"
/>
</p>
<h3 class="font-bold text-lg">{{ t("user.modal title") }}</h3>
<p class="py-4">{{ t("user.modal description") }}</p>
<div class="modal-action">
<label for="key-modal" class="btn btn-primary" @click="handleSubmit"
>{{ t("common.yay") }}!</label
<label
class="btn btn-primary"
:class="{ 'btn-disabled': loading }"
@click="handleSubmit"
>
<span v-if="loading" class="loading loading-spinner" />
<span>{{ t("user.join now") }}!</span>
</label>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/PageLayout/vertical-with-site.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const accountStore = useAccountStore();
class="alert alert-warning shadow-lg mb-10"
v-if="!accountStore.getPrivateKey"
>
<div>
<div class="flex items-center space-x-4">
<svg
xmlns="http://www.w3.org/2000/svg"
class="stroke-current flex-shrink-0 h-6 w-6"
Expand Down
8 changes: 4 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ getServerConfig(app).then(async config => {
setupStore(app);

app.use(useI18n);
app.mount("#app");

// init store if needed
useAccountStore().init();
// get user info from smart contract, for nostr private key
await useAccountStore().init();

// 尝试预获取 instance
app.mount("#app");
try {
// 尝试预获取 instance
await useNostrStore().asyncGetNostrInstance();
} catch (e) {
// ignore
Expand Down
32 changes: 26 additions & 6 deletions src/store/modules/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import { defineStore } from "pinia";
import { store } from "@/store";
import { accountType } from "./types";
import { getPublicKey } from "nostr-tools";
import { storageLocal } from "@pureadmin/utils";
// import { storageLocal } from "@pureadmin/utils";
import { getUserHubContract } from "@/utils/contract/user-hub";
import { handleEtherError, decrypt } from "@/utils/shared";
import { getWalletAddres, signMessage } from "@/utils/contract/web3";

export const useAccountStore = defineStore({
id: "account-settings",
state: (): accountType => ({
name: "",
publicKey: "",
privateKey: storageLocal().getItem("sk") || ""
privateKey: "" //storageLocal().getItem("sk") || ""
}),
getters: {
getPublicKey() {
Expand All @@ -29,9 +32,26 @@ export const useAccountStore = defineStore({
SET_PRIVATEKEY(key: string) {
this.privateKey = key;
},
init() {
if (this.privateKey) {
this.savePrivateKey(this.privateKey);
async init(): Promise<any> {
try {
const address = await getWalletAddres();
const contract = await getUserHubContract();
const data = await contract.getUserInfo(address);
if (!data[0]) return;

const { privateKey } = data[1];
try {
const signKey = await signMessage("CloudX3");
const truePrivateKey = decrypt(privateKey, signKey);
this.savePrivateKey(truePrivateKey);
} catch (e) {
window.alert(
"Please sign the message for build security tunnel with server"
);
// handleEtherError(e);
}
} catch (e) {
handleEtherError(e);
}
},
savePrivateKey(sk: string): string {
Expand All @@ -40,7 +60,7 @@ export const useAccountStore = defineStore({
this.SET_PRIVATEKEY(sk);
this.SET_PUBLICKEY(pk);
this.SET_NAME(pk.substring(0, 2));
storageLocal().setItem("sk", sk);
// storageLocal().setItem("sk", sk);
return "";
} catch (e) {
return e.message;
Expand Down
Loading

0 comments on commit 0c6e93b

Please sign in to comment.