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

Redirect Logged User (for account creation) - DEMO #783

Closed
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
2 changes: 1 addition & 1 deletion env.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const sharedEnv = {
IMGUR_CLIENT_ID: 'b6f46df9d1da9d9',
EVM_CONTRACT: 'eosio.evm',
PROJECT_ID: '2392473d6d98499c7138cd2d705a791f',
GOOGLE_APP_ID: '56634824599-ff3iu788c32c3s7ec65cs4bieop9gpgv.apps.googleusercontent.com', // official App id
GOOGLE_APP_ID: '639241197544-kcubenhmti6u7ef3uj360n2lcl5cmn8c.apps.googleusercontent.com', // Viter's client id
};

const TESTNET = {
Expand Down
2 changes: 1 addition & 1 deletion quasar.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ module.exports = function(/* ctx */) {
// app boot file (/src/boot)
// --> boot files are part of "main.js"
// https://quasar.dev/quasar-cli/boot-files
boot: ['ual', 'hyperion', 'i18n', 'fuel', 'api', 'errorHandling', 'helpers', 'mixin', 'emitter', 'telosApi', 'wagmi', 'antelope'],
boot: ['ual', 'hyperion', 'i18n', 'fuel', 'api', 'errorHandling', 'helpers', 'mixin', 'emitter', 'telosApi', 'wagmi', 'antelope', 'telosCloudJs'],

// https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-css
css: ['index.scss'],
Expand Down
15 changes: 14 additions & 1 deletion src/antelope/wallets/ual/MetakeepUAL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { metakeepCache } from 'src/antelope/wallets/ual/utils/metakeep-cache';
export interface UserCredentials {
email: string;
jwt: string;
keys?: string[];
}

export interface MetakeepUALOptions {
Expand Down Expand Up @@ -64,7 +65,7 @@ export class MetakeepAuthenticator extends Authenticator {
private accountCreateAPI: string;
private appId: string;
private loading = false;
private userCredentials: UserCredentials = { email: '', jwt: '' };
private userCredentials: UserCredentials = { email: '', jwt: '', keys: [] };

private accountSelector: MetakeepAccountSelector = metakeepDefaultAccountSelector;
private accountNameSelector: MetakeepNameAccountSelector = metakeepDefaultAccountNameSelector;
Expand All @@ -89,9 +90,18 @@ export class MetakeepAuthenticator extends Authenticator {
this.userCredentials = {
email: metakeepCache.getLogged() ?? '',
jwt: '',
keys: [],
};
}

getEmail() {
return this.userCredentials.email;
}

getKeys() {
return this.userCredentials.keys;
}

resetAccountSelector() {
this.accountSelector = metakeepDefaultAccountSelector;
}
Expand Down Expand Up @@ -221,6 +231,8 @@ export class MetakeepAuthenticator extends Authenticator {
// we check if we have the account name in the cache
const accountNames = metakeepCache.getAccountNames(this.userCredentials.email, this.chainId);
if (accountNames.length > 0) {
const publicKey = metakeepCache.getEosAddress(this.userCredentials.email);
this.userCredentials.keys = [publicKey];
if (accountNames.length > 1) {
// if we have more than one account, we ask the user to select one using this callback
const selectedAccount = await this.accountSelector.selectAccount(accountNames);
Expand All @@ -236,6 +248,7 @@ export class MetakeepAuthenticator extends Authenticator {
const credentials = await metakeep.getWallet();
const publicKey = credentials.wallet.eosAddress;

this.userCredentials.keys = [publicKey];
metakeepCache.addCredentials(this.userCredentials.email, credentials.wallet);

try {
Expand Down
117 changes: 117 additions & 0 deletions src/boot/telosCloudJs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Redirect or iFrame -----------------------------------------------------------
// if redirect or iframe is set, it means the user is coming from an external source
// and wants to use the wallet to login and come back to the external source
import {
ComponentCustomProperties,
ref,
} from 'vue';
import { boot } from 'quasar/wrappers';

import {
getAntelope,
useAccountStore,
} from 'src/antelope';
import { MetakeepAuthenticator } from 'src/antelope/wallets/ual/MetakeepUAL';
import { createTraceFunction } from 'src/antelope/config';

const url = new URLSearchParams(window.location.search);
export const redirectParam = url.get('redirect');
export const iframeParam = url.get('iframe');
export const logoutParam = url.get('logout');
export const redirect = ref<{url:string, hostname:string} | null>(null);
export const redirectShow = ref(false);
export const iframeShow = ref(false);

const trace = createTraceFunction('telosCloudJs');

// eslint-disable-next-line @typescript-eslint/no-explicit-any
let globalProps = {} as ComponentCustomProperties & Record<string, any>;

export const telosCloudResponse = async () => {
const ant = getAntelope();
const accountStore = useAccountStore();

trace('ant.events.onLoggedIn().....');
// if the redirect parameter is present, show a confirm notification to the user

if (redirectShow.value && redirect.value) {
const hostname = redirect.value.hostname;
const message = globalProps.$t('home.redirect_notification_message', { hostname });
globalProps.$notifyWarningWithAction(message, {
label: ant.config.localizationHandler('home.redirect_me'),
handler: () => {
// we redirect the user to the url
if (redirect.value) {
// we need to generate a new url based on redirect.value?.url adding the accountStore.loggedNativeAccount?.account
// and the email of the user if it's a metakeep authenticator
const url = new URL(redirect.value.url);
trace('onLoggedIn', 'url', url.toString());
url.searchParams.set('account', accountStore.loggedNativeAccount?.account || '');
trace('onLoggedIn', 'adding the account...', url.toString());
const authenticator = accountStore.loggedNativeAccount.authenticator;
trace('onLoggedIn', 'adding the email...', url.toString());
const auth = authenticator as never as MetakeepAuthenticator;
url.searchParams.set('email', auth.getEmail());
trace('onLoggedIn', 'redirecting to', url.toString());
window.location.href = url.toString();
}
},
});
} else if (iframeShow.value) {
// if the iframe parameter is present, we send the credentials to the parent window
const authenticator = accountStore.loggedNativeAccount.authenticator;
const auth = authenticator as never as MetakeepAuthenticator;
const credentials: {account: string, email: string, keys: string[] } = {
account: accountStore.loggedNativeAccount?.account || '',
email: auth.getEmail(),
keys: auth.getKeys() ?? [],
};
const str = JSON.stringify(credentials);
trace('onLoggedIn', 'credentials', credentials, str, 'logoutParam:', logoutParam);
trace('--------------------------------------------------------------------------------');
trace(window.location.href);
trace('--------------------------------------------------------------------------------');
if (logoutParam) {
accountStore.logout();
}
window.parent.postMessage(str, '*');
}
};

export default boot(async ({ app }) => {
const ant = getAntelope();
globalProps = app.config.globalProperties;

if (redirectParam) {
const isValid = new RegExp('^(http|https)://', 'i').test(redirectParam);
if (isValid) {
redirect.value = {
url: redirectParam,
hostname: new URL(redirectParam).hostname,
};
redirectShow.value = true;
}
}

if (iframeParam) {
const isValid = new RegExp('^(http|https)://', 'i').test(iframeParam);
if (isValid) {
redirect.value = {
url: iframeParam,
hostname: new URL(iframeParam).hostname,
};
iframeShow.value = true;
}
}

const subscription = ant.events.onLoggedIn.subscribe({
next: () => {
telosCloudResponse();
subscription.unsubscribe();
},
});


});

console.log('telosCloudJs-0.9.19 support');
3 changes: 3 additions & 0 deletions src/i18n/en-us/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ export default {
account_name: 'Account Name',
name_selection_text: 'Account name needs to be twelve characters long and can only consist of lowercase letters and numerical characters from 1 to 5.',
account_selection_text: 'Choose one of your accounts to log in',
redirect_me: 'Redirect me',
redirect_warning: 'After you log in, you will be redirected to the following site:',
redirect_notification_message: 'Do you approve to be redirected to<br/><b>{hostname}</b>?<br/><br/>only proceed if you trust the site.',
},
nav: {
copy_address: 'Copy address to clipboard',
Expand Down
16 changes: 14 additions & 2 deletions src/pages/home/HomePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import LoginButtons from 'pages/home/LoginButtons.vue';
import { Menu } from 'src/pages/home/MenuType';
import { LocationQueryValue, useRoute, useRouter } from 'vue-router';
import { CURRENT_CONTEXT, useChainStore } from 'src/antelope';
import { iframeParam, redirectParam } from 'src/boot/telosCloudJs';

type TabReference = 'evm' | 'zero' | 'unset';

Expand All @@ -14,6 +15,7 @@ const chainStore = useChainStore();

const tab = ref<TabReference>('unset');
const walletOption = computed(() => route.query.login as LocationQueryValue);
const showTabs = ref(true);

function setChainForTab(tab: TabReference): void {
// set chain
Expand All @@ -40,8 +42,18 @@ function setTab(login: TabReference): void {
}
}

function hideTabs(): void {
showTabs.value = false;
}

onMounted(() => {
if (walletOption.value && walletOption.value !== 'unset') {
// Redirect or iFrame -----------------------------------------------------------
// if redirect or iframe is set, it means the user is coming from an external source
// and wants to use the wallet to login and come back to the external source
if (redirectParam || iframeParam) {
setTab('zero');
hideTabs();
} else if (walletOption.value && walletOption.value !== 'unset') {
setTab(walletOption.value as TabReference);
} else {
// set evm as default
Expand All @@ -62,7 +74,7 @@ onMounted(() => {
class="c-home__logo"
></div>
<div class="c-home__button-container">
<div class="c-home__network-toggle-container" role="tablist">
<div v-if="showTabs" class="c-home__network-toggle-container" role="tablist">
<button
:class="{
'c-home__network-toggle-button': true,
Expand Down
12 changes: 11 additions & 1 deletion src/pages/home/LoginButtons.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import BaseTextInput from 'components/evm/inputs/BaseTextInput.vue';
import NativeChainSettings from 'src/antelope/chains/NativeChainSettings';
import { words } from 'src/pages/home/words';
import { Subscription } from 'rxjs';
import { redirectShow, redirect } from 'src/boot/telosCloudJs';


export default defineComponent({
name: 'LoginButtons',
Expand All @@ -49,6 +51,7 @@ export default defineComponent({
const showEVMButtons = computed(() =>
props.chain === 'evm');
const showZeroButtons = computed(() =>
redirect.value === null && // then we hide everything else
props.chain === 'zero' &&
!requestNameSelection.value &&
!requestAccountSelection.value &&
Expand Down Expand Up @@ -146,6 +149,7 @@ export default defineComponent({

// Telos Zero Login ----------------------------------------------------
const ualAuthenticators = ant.config.authenticatorsGetter();

const loginTelosZero = (idx:number, justViewer:boolean = false) => {
if (justViewer) {
localStorage.setItem('justViewer', 'true');
Expand All @@ -154,6 +158,7 @@ export default defineComponent({
}
const network = chainStore.currentChain.settings.getNetwork();
const authenticator = ualAuthenticators[idx];

accountStore.loginZero({ authenticator, network });
};
const getZeroAuthenticator = (name: string) => {
Expand Down Expand Up @@ -423,6 +428,8 @@ export default defineComponent({
accountNameErrorMessage,
requestAccountSelection,
requestNameSelection,
redirectShow,
redirect,
};
},
unmounted() {
Expand Down Expand Up @@ -524,9 +531,11 @@ export default defineComponent({
</div>
</div>

<template v-if="requestNameSelection || requestAccountSelection">
<template v-if="requestNameSelection || requestAccountSelection || redirectShow">
<div v-if="requestNameSelection" class="c-login-buttons__zero-accounts-title"> {{ $t('home.name_selection_text') }}</div>
<div v-if="requestAccountSelection" class="c-login-buttons__zero-accounts-title"> {{ $t('home.account_selection_text') }}</div>
<div v-if="redirectShow" class="c-login-buttons__zero-accounts-title"> {{ $t('home.redirect_warning') }}</div>
<div v-if="redirectShow" class="c-login-buttons__zero-accounts-title"><b> {{ redirect?.hostname }}</b></div>
</template>

<template v-if="showEVMButtons">
Expand Down Expand Up @@ -663,6 +672,7 @@ export default defineComponent({
{{ $t('home.create_new_account') }}
</div>
</template>

</div>
</template>

Expand Down
Loading