[✨] Fixes + Normal account registration
This commit is contained in:
parent
4a2512d103
commit
b881a650a6
63
index.html
63
index.html
|
@ -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>
|
|
@ -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",
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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>
|
99
src/main.ts
99
src/main.ts
|
@ -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()
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
`
|
||||
`
|
||||
}
|
|
@ -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
|
||||
})
|
|
@ -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: {
|
||||
|
|
Loading…
Reference in New Issue