Firebase reCaptcha keeps stalling and freezing website - Vuejs, Firebase V9 - javascript

I've got the following code that should enable recaptcha and allow users to log in using their phone number. However, whenever I add a phone number and click sign in, the site just freezes, the recpatcha box appears but then nothing happens. I can't see any errors from my console.
Vue3 on Vite using Firebase V9
import { ref } from 'vue'
import { getAuth, RecaptchaVerifier, signInWithPhoneNumber } from "firebase/auth"
const auth = getAuth()
const userPhone = ref(null)
const phoneCode = ref('+44')
const conCode = ref('');
const smsSent = ref(false)
const confirmationResult = ref(null)
const initRecaptcha = () => {
setTimeout(()=>{
window.recaptchaVerifier = new RecaptchaVerifier('sign-in-button', {
size: 'invisible',
'callback': (response) => {
// reCAPTCHA solved, allow signInWithPhoneNumber.
console.log(response)
}}, auth)
},1000)
}
initRecaptcha()
const SignIn = async() => {
const appVerifier = window.recaptchaVerifier
const phonenumber = `${phoneCode.value}${userPhone.value}`
console.log(`${phoneCode.value}${userPhone.value}`)
signInWithPhoneNumber(auth, phonenumber, appVerifier)
.then((confirmationresult) => {
// SMS sent. Prompt user to type the code from the message, then sign the
// user in with confirmationResult.confirm(code).
// ...
window.confirmationResult = confirmationresult;
smsSent.value = true
alert('SMS sent')
}).catch((error) => {
// Error; SMS not sent
// ...
window.recaptchaVerifier.render().then(function(widgetId) {
grecaptcha.reset(widgetId);
})
console.log('Theres been an error', error)
});
}
const confirmCode = async() => {
const code = conCode.value
try {
const result = await confirmationResult.value.confirm(code)
// User signed in successfully.
const user = result.user;
console.log('User details are ', user)
// ...
} catch (error) {
// User couldn't sign in (bad verification code?)
// ...
console.log('BIG ERROR', error)
};
}
</script>
<template>
<div class="px-14 mt-12">
<div id="re-element"></div>
<form v-if="smsSent == false" id="sign-in-form">
<!-- Input to enter the phone number -->
<div class="flex relative shadow-md">
<div class="absolute inset-y-0 left-0 pl-3 my-auto align-middle flex text-gray-300 text-center pointer-events-none"><p class="flex items-middle">(+44)0</p></div>
<input
v-model="userPhone" type="tel" id="phone-number"
class="px-3 py-4 flex-1
pl-16 font-extralight text-gray-600 relative bg-opacity-0 bg-transparent border-2 border-gray-900 bg-gray-800outline-none focus:z-10 focus:outline-none w-full"
/>
<label class="absolute top-2.5 ml-4 px-8 pt-1 -z-1 text-normal font-light duration-300 origin-0 text-gray-500" for="phone-number">Enter your phone number...</label>
<!-- Sign-in button -->
<button #click.prevent="SignIn" class="flex-0 px-4 border-2 border-gray-900" id="sign-in-button">Sign-in</button>
</div>
</form>
<form v-else id="verification-code-form">
<!-- Input to enter the verification code -->
<div class="flex">
<input v-model="conCode" class="" type="text" id="verification-code">
<label class="" for="verification-code">Enter the verification code...</label>
</div>
<!-- Button that triggers code verification -->
<button #click.prevent="confirmCode" class="text-grey-800" id="verify-code-button" value="Verify Code">Verify code</button>
<!-- Button to cancel code verification -->
<button class="" id="cancel-verify-code-button">Cancel</button>
</form>
<div id="phone-sign-in-recaptcha"></div>
</div>
</template>
<style scoped>
input:focus-within ~ label,
input:not(:placeholder-shown) ~ label {
#apply transform scale-75 -translate-y-3.5 px-6;
}
input:focus-within ~ label {
#apply text-blue-500;
}
</style>
Am I missing something wildly obvious? I've been stuck of this for some time haha. Thanks in advance.

Related

Not connect to credential provider sidebase nuxt auth

I am using sidebase nuxt auth for my application. I am trying to connect to my database via axios. This code works, i get no error from database but not through sidebase auth. The result returns true, but at the same time I am thrown to a page with an authorization error. And in index.vue i got status from useSession() = not authorized. Can you help me?
this is file index.vue where is form define
<template>
<section class="agents-enter">
{{status}}
<div class="container-fluid">
<div class="row">
<div class="col-12 col-lg-6 col-xl-7 d-flex flex-column">
<SectionTitle
title="Партнерам"
subtitle="Приглашаем агентов к сотрудничеству по продаже автобусных билетов"
description="Описание о том, что это и как это работает"
/>
<!-- <img v-if="!isMobile()" class="image-section" alt="Агенты" src="/img/agents/agents.svg"> -->
</div>
<div class="col-12 col-lg-6 col-xl-5 d-flex justify-content-end">
<div class="login-form-wrapper">
<div class="login-form">
<h3 class="title-form text-center">
Вход для агентов
</h3>
<form #submit.prevent="signIn('credentials', { username: userStore.username, password: userStore.password })">
<!-- TODO добавить is-ok-bordered или is-error-bordered для валидации-->
<div class="form-group">
<label for="login" class="form-label">Эл. почта</label>
<div class="position-relative">
<input v-model="userStore.username" id="mail" type="text" class="form-control" name="mail" placeholder="Введите email">
<div class="form-icon-wrapper">
<IconsMail class="form-icon" color="#B5BDDB" />
</div>
<div class="is-error-icon d-none">
<IconsMail class="form-icon" color="#fff" />
</div>
</div>
<div class="error-feedback-bordered d-none">
Неверная почта
</div>
</div>
<div class="form-group">
<label for="passwordInputForm" class="form-label">Пароль</label>
<div class="position-relative">
<input v-model="userStore.password" id="passwordInputForm" type="password" class="form-control" name="password" placeholder="Введите пароль">
<div class="form-icon-wrapper">
<IconsPassword class="form-icon" color="#B5BDDB" />
</div>
<div class="is-error-icon d-none">
<IconsPassword class="form-icon" color="#fff" />
</div>
</div>
<div class="error-feedback-bordered d-none">
Неверный пароль
</div>
</div>
<div class="d-grid mt-4">
<button :class="{'btn-disabled' : !userStore.username || !userStore.password}" type="submit" class="btn d-block">
Войти
</button>
</div>
</form>
<ForgotPasswordLink class="forgotPasswordLink" />
</div>
</div>
</div>
</div>
</div>
</section>
<ForgotPasswordModal />
</template>
<script setup>
import {useUserStore} from "~/stores/userStore";
const userStore = useUserStore()
const { status, data, signIn, signOut } = useSession()
</script>
<script>
export default {
name: "index",
}
</script>
<style scoped>
</style>
and this is auth file, when is logic need to be done. My path is server/api/auth/[...].ts
// file: ~/server/api/auth/[...].ts
import { NuxtAuthHandler } from '#auth'
import CredentialsProvider from "next-auth/providers/credentials";
import axios from "axios";
export default NuxtAuthHandler({
secret: 'your-secret-here',
session: {
strategy: 'jwt'
},
jwt: {
// The maximum age of the NextAuth.js issued JWT in seconds.
// Defaults to `session.maxAge`.
maxAge: 60 * 60 * 24 * 30,
},
providers: [
// #ts-expect-error You need to use .default here for it to work during SSR. May be fixed via Vite at some point
CredentialsProvider.default({
// The name to display on the sign in form (e.g. 'Sign in with...')
name: 'Credentials',
// The credentials is used to generate a suitable form on the sign in page.
// You can specify whatever fields you are expecting to be submitted.
// e.g. domain, username, password, 2FA token, etc.
// You can pass any HTML attribute to the <input> tag through the object.
credentials: {
username: { label: 'Username', type: 'text'},
password: { label: 'Password', type: 'password'}
},
async authorize (credentials: any) {
try {
// You need to provide your own logic here that takes the credentials
// submitted and returns either a object representing a user or value
// that is false/null if the credentials are invalid.
const usernameForm = credentials?.username
const passwordForm = credentials?.password
const config = {
url: 'https://api3.evrotrans.net/auth/login',
credentials: 'include',
method: 'post',
headers: {
"Content-type": "application/json; charset=UTF-8"
},
data: '{\"login\":\"' + usernameForm +'\",\"password\":\"' + passwordForm + '\"}',
}
await axios.request(config).then((response) => {
const user = {username: usernameForm, password: passwordForm, token: response.data.token}
console.log(response.data.message)
if (response.data.error == 0) {
// Any object returned will be saved in `user` property of the JWT
console.log('авторизован')
return true
}
if (response.data.password == 'Incorrect login or password.') {
console.error('неправильный логин или пароль')
return null
}
})
}
catch (e) {
console.log(e)
return e
}
}
})
],
})
The problem was in axios.
My solution for this:
let response = await axios.post('https://api3.evrotrans.net/auth/login', {
credentials: 'include',
headers: {
"Content-type": "application/json; charset=UTF-8"
},
login: usernameForm,
password: passwordForm
})
if (response.data.error == 0) {
response.data.username = usernameForm
const user = response.data
console.log(user)
return user
}

Search query box doesn't recommend places in Vue automatically

If you run my below code, it is supposed to open up a website. This works fine, however, when I go to the input box it is supposed to recommend places with the characters given immediately. This isn't working.
I am doing a tutorial and am currently at 12:41 of this video.
https://www.youtube.com/watch?v=5pTzHoliXUQ&list=PL4cUxeGkcC9hfoy8vFQ5tbXO3vY0xhhUZ&index=5
Here is my code:
<template>
<main class="container text-white" >
<div class="pt-4 mb-8 relative">
<input type="text"
v-model = "searchQuery"
#input="getSearchResults"
placeholder="Search for city or state"
class="py-2 px-1 w-full bg-transparent border-b
focus:border-weather-secondary focus:outline-none focus:shadow-[0px_1px_0_0_#004E71]">
<ul class="absolute bg-weather-secondary text-white w-full shadow-md py-2 px-1 top-[66px]">
<li v-for="searchResult in mapboxSearchResults" :key ="searchResult.id" class="py-2 cursor-pointer">
{{searchResult.place_name}}
</li>
</ul>
</div>
</main>
</template>
<script setup>
import { ref } from 'vue';
import axios from 'axios';
const mapboxAPIkey ="pk.eyJ1IjoiYWhhbmFhYSIsImEiOiJjbGJqc3d5NG0xNGd5M3BtbWppcmgyNzE4In0.L-HsHWAbshfvVY_xixizNw"
const searchQuery = ref("");
const queryTimeout = ref(null)
const mapboxSearchResults = ref(null)
const getResults = () => {
clearTimeout(queryTimeout.value)
queryTimeout.value = setTimeout(async() => {
if(searchQuery.value !== ""){
const result = await axios.get(
`https://api.mapbox.com/geocoding/v5/mapbox.places/${searchQuery.value}.json?access_token=${mapboxAPIkey}&types=place`
)
mapboxSearchresults.value = result.data.features
return;
}
mapboxSearchresults.value = null
}, 300)
}
</script>
I tried to run the code with npm run dev in the terminal and everything was working fine up until now.

Programmatically Set an href Link in React

I have a product that I want to programatically set a Checkout Session URL and then redirect a user when they click on an tag.
const PlanComponent = () => {
const [tiers, setTiers] = useState([]);
async function CheckoutSessionUrl(tierId) {
var result = null
await CreateCheckoutSession(
"PRODUCT_ID",
tierId,
"UID"
).then(function(response) {
result = response
})
return result;
};
async function LoadProducts() {
var result = []
await GetProducts("PRODUCT_ID").then(function(response) {
for (var i = 0; i < response.length; i++) {
var tier_id = response[i]["tier_id"]
CheckoutSessionUrl(tier_id).then(function(tier_response) {
response[i]["url"] = tier_response;
})
}
console.log("printing tiers");
console.log(response);
return response;
}).then(function(response){
result = response;
setTiers(result)
return result;
});
return result;
}
useEffect(() => {
// Some initialization logic here
LoadProducts().then(function(response) {
console.log("setting tiers")
console.log(response)
//setTiers(response)
})
}, []);
return (
<div className="bg-white">
<div className="max-w-7xl mx-auto py-24 px-4 sm:px-6 lg:px-8">
<div className="sm:flex sm:flex-col sm:align-center">
<h1 className="text-5xl font-extrabold text-gray-900 sm:text-center">Pricing Plans</h1>
<p className="mt-5 text-xl text-gray-500 sm:text-center">
Start building for free, then add a site plan to go live. Account plans unlock additional features.
</p>
</div>
<div className="mt-12 space-y-4 sm:mt-16 sm:space-y-0 sm:grid sm:grid-cols-2 sm:gap-6 lg:max-w-4xl lg:mx-auto xl:max-w-none xl:mx-0 xl:grid-cols-4">
{tiers.map((tier) => (
<div key={tier.name} className="border border-gray-200 rounded-lg shadow-sm divide-y divide-gray-200">
<div className="p-6">
<h2 className="text-lg leading-6 font-medium text-gray-900">{tier.name}</h2>
<p className="mt-4 text-sm text-gray-500">{tier.description}</p>
<p className="mt-8">
<span className="text-4xl font-extrabold text-gray-900">${tier.price}</span>{' '}
<span className="text-base font-medium text-gray-500">/mo</span>
</p>
<a
href={tier.url}
className="mt-8 block w-full bg-gray-800 border border-gray-800 rounded-md py-2 text-sm font-semibold text-white text-center hover:bg-gray-900"
>
Buy {tier.name}
</a>
</div>
<div className="pt-6 pb-8 px-6">
<h3 className="text-xs font-medium text-gray-900 tracking-wide uppercase">What's included</h3>
<ul role="list" className="mt-6 space-y-4">
{tier.users.map((feature) => (
<li key={feature} className="flex space-x-3">
{/*<CheckIcon className="flex-shrink-0 h-5 w-5 text-green-500" aria-hidden="true" />*/}
<span className="text-sm text-gray-500">{feature}</span>
</li>
))}
</ul>
</div>
</div>
))}
</div>
</div>
</div>
)
}
so if you look at the href={tier.url} it's not being set correctly. I feel like I'm not doing this correctly. Would love some feedback on how to actually get this working properly. IT looks like the tier.url new field isn't being set correctly (doesn't exist in the initial request but all the other attributes work).
The other option I wanted to do was when a user clicked a Button, it would generate a URL and redirect a user to that new external url but the navigation kept breaking.
Oh I found out what was happening. I needed to replace
await GetProducts("PRODUCT_ID").then(function(response) {
with
await GetProducts("PRODUCT_ID").then(async function(response) {

I am having problems with CSS when I open my code in localhost

I saw this code in an article about discord Oauth2. As I have two HTML files so how do I connect both of them in this line: res.sendFile('index.html', { root: '.' });
And my both HTML files are not in a specific folder it's in the main file.
When I open my code with VS code live server it looks like this:
But when I open it with localhost:53134 it looks like this:
This is my index.html code:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Montserrat Google Font -->
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght#900&display=swap" rel="stylesheet">
<!-- Changes this to your bot's name -->
<title>Discord Bot Website Template</title>
<!-- Change the content attribute's value to your bot's description -->
<meta name="description" content="An opensource discord bot website template that you can use to make your bot seem more professional!">
<!-- Change the content attribute's value to your name -->
<meta name="author" content="TrustedMercury">
<link rel="stylesheet" href="styles/theTrendingStyle.css">
<link rel="stylesheet" href="styles/index.css">
<link rel="stylesheet" href="styles/css/all.css" />
</head>
<body class="bg-shinyGray overflow-x-hidden">
<nav id="navigationBar" class="flex flex-row items-center justify-between p-6 bg-sweetBlack">
<div class="left flex flex-row items-center ml-10 md:ml-20 text-white">
<img src="images/botLogo.png" width="48px" height="48px" class="mr-2 hidden md:inline pointer-events-none noselect" />
Home
Pricing
</div>
<div class="right mr-10 md:mr-20">
<i class="fab fa-discord mr-1"></i> Invite
<div id="info">
Hoi!
</div>
</div>
</nav>
<div id="container" class="flex flex-col items-center justify-center">
<div class="flex flex-col items-center justify-center pt-40 text-center">
<span class="text-2xl md:text-5xl font-semibold text-white">Changing the way servers work</span>
<span class="text-gray-400 text-lg md:text-xl max-w-xl font-light">Helping servers grow exponentially with a simple solution. Make your server active and entertain your community with a simple solution - <b>a single discord bot</b>!</span>
<div class="flex flex-col md:flex-row mt-8">
Invite the bot now!
Join the Support Server
</div>
</div>
<svg class="bg-blurple" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320"><path fill="#1D1E23" fill-opacity="1" d="M0,160L48,138.7C96,117,192,75,288,74.7C384,75,480,117,576,160C672,203,768,245,864,261.3C960,277,1056,267,1152,240C1248,213,1344,171,1392,149.3L1440,128L1440,0L1392,0C1344,0,1248,0,1152,0C1056,0,960,0,864,0C768,0,672,0,576,0C480,0,384,0,288,0C192,0,96,0,48,0L0,0Z"></path></svg>
<div class="flex flex-col md:flex-row items-center justify-center w-full bg-blurple">
<img src="images/discordUI.png" class="max-w-xs md:max-w-5xl noselect pointer-events-none" />
<div class="flex flex-col items-center justify-center noselect">
<div class="flex flex-col items-center text-4xl mb-4">
<span class="font-montserrat font-black">200+</span>
<span class="font-montserrat font-black">SERVERS</span>
</div>
<div class="flex flex-col items-center text-4xl my-4">
<span class="font-montserrat font-black">14500+</span>
<span class="font-montserrat font-black">USERS</span>
</div>
<div class="flex flex-col items-center text-4xl mt-4">
<span class="font-montserrat font-black">2300+</span>
<span class="font-montserrat font-black">CHANNELS</span>
</div>
</div>
</div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320"><path fill="#7289DA" fill-opacity="1" d="M0,224L48,240C96,256,192,288,288,304C384,320,480,320,576,288C672,256,768,192,864,138.7C960,85,1056,43,1152,48C1248,53,1344,107,1392,133.3L1440,160L1440,0L1392,0C1344,0,1248,0,1152,0C1056,0,960,0,864,0C768,0,672,0,576,0C480,0,384,0,288,0C192,0,96,0,48,0L0,0Z"></path></svg>
<div class="flex flex-row items-center justify-center mb-10">
<span class="text-lg text-gray-400 font-semibold">Copyright © Kevin Thomas 2020</span>
</div>
</div>
<a id="login" style="display: none;" href="Oauth link here">Identify Yourself</a>
<script>
function generateRandomString() {
const rand = Math.floor(Math.random() * 10);
let randStr = '';
for (let i = 0; i < 20 + rand; i++) {
randStr += String.fromCharCode(33 + Math.floor(Math.random() * 94));
}
return randStr;
}
window.onload = function () {
const fragment = parseQuery(window.location.href);
if (fragment.access_token) {
const urlState = fragment.state;
const stateParameter = localStorage.getItem('stateParameter');
if (stateParameter !== atob(decodeURIComponent(urlState))) {
return console.log('You may have been clickjacked!');
}
const accessToken = fragment.access_token;
const tokenType = fragment.token_type;
fetch('https://discordapp.com/api/users/#me', {
headers: {
authorization: `${tokenType} ${accessToken}`
}
})
.then(res => res.json())
.then( (response) => {
console.log(response);
const { username, discriminator, avatar } = response;
document.getElementById('info').innerHTML = ` ${username}#${discriminator}`;
let user = provider.getResourceOwner(`${accessToken}`);
let avatar1 = 'https://cdn.discordapp.com/avatars/' + user.id + '/' + user.avatar + '.png ?size=225';
document.getElementsByClassName("avatar-img").src = avatar1;
})
.catch(console.error);
} else {
const randStr = generateRandomString();
localStorage.setItem('stateParameter', randStr);
document.getElementById('login').href += `&state=${encodeURIComponent(btoa(randStr))}`;
document.getElementById('login').style.display = 'block';
}
}
function parseQuery(queryString) {
var query = {};
var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');
}
return query;
}
</script>
<script src="main.js"></script>
</body>
</html>
This is my javascript code:
const app = require('express')();
const fetch = require('node-fetch');
app.get('/', async (req, res) => {
let access_token;
let token_type;
if (req.query.code) {
const accessCode = req.query.code;
const data = {
client_id : 'client id here',
client_secret : 'client secret here',
grant_type : 'authorization_code',
redirect_uri : 'http://localhost:3000',
code : accessCode,
scope : 'identify'
};
const res = await fetch('https://discordapp.com/api/oauth2/token', {
method : 'POST',
body : new URLSearchParams(data),
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
}
});
const info = await res.json();
token_type = info.token_type;
access_token = info.access_token;
const post = await fetch('https://discordapp.com/api/users/#me', {
headers : {
authorization : `${token_type} ${access_token}`
}
});
const user = await post.json();
}
if (token_type && access_token && req.query.state) {
res
.status(200)
.redirect(
`http://localhost:3000/?code=${req.query.code}&state=${req.query
.state}&access_token=${access_token}&token_type=${token_type}`
);
} else {
res.sendFile('index.html', { root: '.' });
}
});
app.listen(3000);

alpine.js $dispatch modal -> submit Form

I am using django and i have a base template where i defined a modal using alpine.js with $dispatch sender.
base.html:
<div x-data="modal()" class="mt-6" x-cloak>
<template x-on:show-modal.window="isOpenModal = $event.detail.show; modalHeader = $event.detail.modalHeader; modalData = showData($event.detail.modalData); "></template>
<div class="absolute z-50 top-0 left-0 w-full h-full flex items-center justify-center bg-black bg-opacity-50" x-show="isOpenModal">
<div class="z-50 text-left bg-gray-200 px-4 shadow-xl rounded-lg mx-2 md:max-w-lg md:p-6 lg:p-8 md:mx-0 h-auto " >
<div class="flex justify-between">
<h2 id="modalHeader" class="text-2xl" x-text="modalHeader"> </h2>
</div>
<div class="w-full border border-gray-600 mt-4" ></div>
<div id="modalContent" class="text-lg w-auto" > </div>
</div>
</div>
</div>
in script tags ....
function modal(){
return{
isOpenModal: false,
modalHeader:'',
modalData: '',
showData(data){
document.getElementById('modalContent').innerHTML = data
let fp = flatpickr(".pickerDate", {locale: "at", dateFormat: "d.m.Y"});
},
}
}
then in the other html which is extendet from the base.html i want to use the modal where i want to get with axios form data from the server and put it into the modal. This is working perfect. But i don't know how to realize the submit button ?
new.html
<div x-data="test()" #click="getCreateForm($dispatch)">
test click
</div>
this is the point where i go to function getCreateForm ....
function test(){
return{
getPatientCreateForm($dispatch){
axios.get("{% url 'user:createForm'%}")
.then(response => {
var modalHeader = response.data.header
var modalData = "<form id='createUser' class='' method='POST' action='' x-on:submit.prevent='?????????'> {% csrf_token %}" +response.data.seite.seite
$dispatch('show-modal', { show: true, modalHeader: modalHeader, modalData: modalData })
})
.catch(error => {
console.log(error);
})
}
}
}
The problem is when i put a sendForm function into the submit.prevent like: x-on:submit.prevent='sendForm()' alpine searches for the function on the base.html (where the modal is defined) and i don't want to implement a function there. I want by clicking the submit button that the data should be send with axios on the new.html (where i started with the getCreateForm ) and not at the base.html. Is that possible with alpine.js and $dispatch ? or is that impossible
Thanks for helping!
Martin

Categories