[] Fixes + Normal account registration

This commit is contained in:
Anthony 2022-11-24 15:13:53 +00:00
parent 4a2512d103
commit b881a650a6
8 changed files with 155 additions and 95 deletions

View File

@ -17,7 +17,6 @@
<title>Apexie's Hub</title>
<link rel="stylesheet" href="/assets/css/style.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.3/font/bootstrap-icons.css">
<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js"></script>
</head>
@ -27,7 +26,7 @@
<div class="container">
<a class="navbar-brand" href="#">
<img src="assets/img/favicon.png" alt="" width="30" height="30" class="d-inline-block align-text-top">
Apexie's Home
Apexie's Hub
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
@ -37,21 +36,21 @@
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
<a class="nav-link active" aria-current="page" href="#"><i class="bi bi-house"></i> Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://github.com/apexiedev">GitHub</a>
<a class="nav-link" href="https://github.com/apexiedev"><i class="bi bi-github"></i> GitHub</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://dsc.gg/apexie">Discord</a>
<a class="nav-link" href="https://dsc.gg/apexie"><i class="bi bi-discord"></i> Discord</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
Projects
<i class="bi bi-braces"></i> Projects
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="#osustream">osu!stream revived</a></li>
<li><a class="dropdown-item" href="#osustream">osu!restream</a></li>
<li><a class="dropdown-item" href="#plenus">Plenus</a></li>
<li>
<hr class="dropdown-divider">
@ -68,7 +67,7 @@
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
Profile
<i class="bi bi-person-circle"></i> Profile
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" id="login_button" data-bs-toggle="modal"
@ -91,11 +90,15 @@
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Login to the Apexie World</h1>
<h1 class="modal-title fs-5" id="loginModalLabel">Login to your Apexie ID</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="modal-body" id="loginModalBody">
<form>
<div class="mb-3" id="account-username-fill" hidden>
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="account-username">
</div>
<div class="mb-3">
<label for="account-email" class="form-label">Email address</label>
<input type="email" class="form-control" id="account-email" aria-describedby="emailHelp">
@ -105,17 +108,18 @@
<label for="account-password" class="form-label">Password</label>
<input type="password" class="form-control" id="account-password">
</div>
<div class="mb-3" id="account-confirm-password-fill" hidden>
<label for="account-confirm-password" class="form-label">Confirm Password</label>
<input type="password" class="form-control" id="account-confirm-password">
</div>
</form>
<div id="login-error"></div>
<div id="verification-alert"></div>
<ul id="login-list">
<li>Loading OAuth2 providers...</li>
</ul>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" id="account-register" class="btn btn-primary">Register</button>
<button type="submit" id="account-login" class="btn btn-primary">Login</button>
<div class="modal-footer" id="loginModalFooter">
</div>
</div>
</div>
@ -150,33 +154,6 @@
</div>
</div>
<div class="modal fade" id="sessionexpired" tabindex="-2" aria-labelledby="logintime" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="expiredLabel">Login expired</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p class="lead">Hi, it seems like your Discord session on this website has expired, would you like
to login again?</p>
</div>
<div class="modal-footer">
<!-- Yes -->
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id="login-yes">
Yes
</button>
<!-- No -->
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id="login-no">
No
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id="login-dont-show">
Don't show this again
</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="gdprconsent" tabindex="-2" aria-labelledby="gdpr" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
@ -202,10 +179,8 @@
</div>
</div>
</div>
<div id="main-app"></div>
<script type="module" src="/src/main.ts"></script>
<script type="module" src="/src/homepage.ts"></script>
</body>
</html>

View File

@ -12,6 +12,7 @@
"@types/bootstrap": "^5.2.6",
"@types/jquery": "^3.5.14",
"bootstrap": "^5.2.3",
"bootstrap-icons": "^1.10.2",
"pocketbase": "^0.8.0",
"sass": "^1.56.1",
"typescript": "^4.6.4",

View File

@ -5,6 +5,7 @@ specifiers:
'@types/bootstrap': ^5.2.6
'@types/jquery': ^3.5.14
bootstrap: ^5.2.3
bootstrap-icons: ^1.10.2
pocketbase: ^0.8.0
sass: ^1.56.1
typescript: ^4.6.4
@ -17,6 +18,7 @@ devDependencies:
'@types/bootstrap': 5.2.6
'@types/jquery': 3.5.14
bootstrap: 5.2.3_@popperjs+core@2.11.6
bootstrap-icons: 1.10.2
pocketbase: 0.8.0
sass: 1.56.1
typescript: 4.9.3
@ -74,6 +76,10 @@ packages:
engines: {node: '>=8'}
dev: true
/bootstrap-icons/1.10.2:
resolution: {integrity: sha512-PTPYadRn1AMGr+QTSxe4ZCc+Wzv9DGZxbi3lNse/dajqV31n2/wl/7NX78ZpkvFgRNmH4ogdIQPQmxAfhEV6nA==}
dev: true
/bootstrap/5.2.3_@popperjs+core@2.11.6:
resolution: {integrity: sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==}
peerDependencies:

View File

@ -6,39 +6,6 @@
</head>
<body>
<pre id="content">Authenticating...</pre>
<script src="https://cdn.jsdelivr.net/gh/pocketbase/js-sdk@master/dist/pocketbase.umd.js"></script>
<script type="text/javascript">
const pb = new PocketBase("https://imlighty-redesigned-enigma-75x56qwx6rhrv7v-8090.preview.app.github.dev/");
const redirectUrl = 'https://imlighty-redesigned-enigma-75x56qwx6rhrv7v-5173.preview.app.github.dev/redirect.html';
// parse the query parameters from the redirected url
const params = (new URL(window.location)).searchParams;
// load the previously stored provider's data
const provider = JSON.parse(localStorage.getItem('provider'))
// compare the redirect's state param and the stored provider's one
if (provider.state !== params.get('state')) {
throw "State parameters don't match.";
}
// authenticate
pb.collection('users').authWithOAuth2(
provider.name,
params.get('code'),
provider.codeVerifier,
redirectUrl,
// pass optional user create data
{
emailVisibility: false,
}
).then((authData) => {
// document.getElementById('content').innerText = JSON.stringify(authData, null, 2);
window.location = '/'
}).catch((err) => {
document.getElementById('content').innerText = "Failed to exchange code.\n" + err;
});
</script>
<script type="module" src="/src/pages/redirect.ts"></script>
</body>
</html>

View File

@ -1,4 +1,5 @@
import './scss/styles.scss'
import 'bootstrap-icons/font/bootstrap-icons.css'
import * as bootstrap from 'bootstrap'
import pocketbase from 'pocketbase'
@ -12,15 +13,47 @@ console.log("%cWARNING!!!" +
"color: red; font-size: 30px;",
"color: black; font-size: 15px;")
const params = (new URL(window.location.toString())).searchParams
if (params.get('confirm_token')) {
await pb.collection('users').confirmVerification(params.get('confirm_token')!).then(() => {
prepareLoginModal(false)
$('#loginModal').modal('show')
$('#verification-alert').html(`
<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>Success!</strong> Your email address has been verified.
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
`)
}).catch((err) => {
prepareLoginModal(false)
$('#loginModal').modal('show')
$('#verification-alert').html(`
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<strong>Error!</strong> ${err}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
`)
})
}
if (params.get('page')) {
} else {
const homepage = await import('./pages/homepage')
homepage.default()
}
let gdprConsent = localStorage.getItem("apexie-gdprconsent")!
let gdprConsentModal = new bootstrap.Modal(document.getElementById("gdprconsent")!)
async function loadLinks() {
async function loadLinks(register?: boolean) {
const authMethods = await pb.collection('users').listAuthMethods()
const listItems: any = []
for (const provider of authMethods.authProviders) {
const $li = $(`<li><a>Login with ${provider.name}</a></li>`)
let $li = $(`<li><a>Login with ${provider.name}</a></li>`)
if (register) $li = $(`<li><a>Register with ${provider.name}</a></li>`)
$li.find('a')
.attr('href', provider.authUrl + redirectUrl)
@ -37,17 +70,61 @@ async function loadLinks() {
}
document.getElementById('login_button')!.addEventListener('click', () => loadLinks())
async function prepareLoginModal(register: boolean) {
if (register) {
document.querySelector<HTMLHeadingElement>('#loginModalLabel')!.innerText = 'Create your Apexie ID'
document.querySelector<HTMLDivElement>('#loginModalFooter')!.innerHTML = `
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="account-register-submit">Register</button>
`
document.querySelector<HTMLButtonElement>('#account-register-submit')!.addEventListener('click', async () => {
const data = {
"username": document.querySelector<HTMLInputElement>('#account-username')!.value,
"email": document.querySelector<HTMLInputElement>('#account-email')!.value,
"emailVisibility": false,
"password": document.querySelector<HTMLInputElement>('#account-password')!.value,
"passwordConfirm": document.querySelector<HTMLInputElement>('#account-confirm-password')!.value,
"name": document.querySelector<HTMLInputElement>('#account-username')!.value,
}
await pb.collection('users').create(data);
await pb.collection('users').requestVerification(data.email)
$('#verification-alert').html(`
<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>Verification email sent!</strong> Please check your inbox and click the link to verify your email address.
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
`)
})
} else {
document.querySelector<HTMLHeadingElement>('#loginModalLabel')!.innerText = 'Login to your Apexie ID'
document.querySelector<HTMLDivElement>('#loginModalFooter')!.innerHTML = `
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" id="account-register" class="btn btn-primary">Register</button>
<button type="submit" id="account-login" class="btn btn-primary">Login</button>
`
}
document.querySelector<HTMLDivElement>('#account-username-fill')!.hidden = !register
document.querySelector<HTMLDivElement>('#account-confirm-password-fill')!.hidden = !register
document.getElementById('account-register')!.addEventListener('click', () => prepareLoginModal(true))
document.getElementById('account-login')!.addEventListener('click', async () => {
login_error.innerHTML = ''
await pb.collection('users').authWithPassword((<HTMLInputElement>document.getElementById('account-email')!).value, (<HTMLInputElement>document.getElementById('account-password')!).value).catch(() => {
login_error.innerHTML = 'Failed to authenticate. Please try again.<p>'
document.querySelector<HTMLInputElement>('#account-password')!.value = ''
})
})
loadLinks(register)
}
document.getElementById('login_button')!.addEventListener('click', () => prepareLoginModal(false))
let login_error = document.querySelector<HTMLDivElement>('#login-error')!
document.getElementById('account-login')!.addEventListener('click', async () => {
login_error.innerHTML = ''
await pb.collection('users').authWithPassword((<HTMLInputElement>document.getElementById('account-email')!).value, (<HTMLInputElement>document.getElementById('account-password')!).value).catch((err) => {
login_error.innerHTML = 'Failed to authenticate. Please try again.<p>'
document.querySelector<HTMLInputElement>('#account-password')!.value = ''
})
})
if (!gdprConsent) {
gdprConsentModal.show()
@ -57,4 +134,4 @@ if (!gdprConsent) {
localStorage.setItem("apexie-gdprconsent", "true")
gdprConsentModal.hide()
})
}
}

View File

@ -1,7 +1,8 @@
import './scss/styles.scss'
import '../scss/styles.scss'
document.querySelector<HTMLDivElement>('#main-app')!.innerHTML = `
<section class="bg-dark text-light p-5 p-lg-0 pt-lg-5 text-center text-sm-start">
export default function () {
document.querySelector<HTMLDivElement>('#main-app')!.innerHTML = `
<section class="bg-dark text-light p-5 p-lg-0 pt-lg-5 text-center text-sm-start">
<div class="container">
<div class="d-sm-flex align-items-center justify-content-between">
<div>
@ -81,7 +82,7 @@ document.querySelector<HTMLDivElement>('#main-app')!.innerHTML = `
<img src="assets/img/osu!stream.jpg" class="img-fluid" alt="" />
</div>
<div class="col-md p-5">
<h2>osu!stream revived</h2>
<h2>osu!restream</h2>
<p class="lead">
The best take on an osu!stream port
that you can find.
@ -139,4 +140,5 @@ document.querySelector<HTMLDivElement>('#main-app')!.innerHTML = `
</a>
</div>
</footer>
`
`
}

32
src/pages/redirect.ts Normal file
View File

@ -0,0 +1,32 @@
import PocketBase from 'pocketbase'
const pb = new PocketBase("https://imlighty-redesigned-enigma-75x56qwx6rhrv7v-8090.preview.app.github.dev/")
const redirectUrl = 'https://imlighty-redesigned-enigma-75x56qwx6rhrv7v-5173.preview.app.github.dev/redirect.html'
// parse the query parameters from the redirected url
const params = (new URL(window.location.toString())).searchParams
// load the previously stored provider's data
const provider = JSON.parse(localStorage.getItem('provider')!)
// compare the redirect's state param and the stored provider's one
if (provider.state !== params.get('state')) {
throw "State parameters don't match."
}
// authenticate
pb.collection('users').authWithOAuth2(
provider.name,
params.get('code')!,
provider.codeVerifier,
redirectUrl,
// pass optional user create data
{
emailVisibility: false,
}
).then(() => {
// document.getElementById('content').innerText = JSON.stringify(authData, null, 2);
new Location().assign('/')
}).catch((err) => {
document.getElementById('content')!.innerText = "Failed to exchange code.\n" + err
})

View File

@ -3,7 +3,7 @@ import path from 'path'
export default {
resolve: {
alias: {
'~bootstrap': path.resolve(__dirname, 'node_modules/bootstrap'),
'~bootstrap': path.resolve(__dirname, 'node_modules/bootstrap')
}
},
server: {