✨ Closes #273
This commit is contained in:
@@ -54,6 +54,7 @@ class Settings(BaseSettings):
|
|||||||
free_storage_limit: int = 1074000000
|
free_storage_limit: int = 1074000000
|
||||||
pixabay_api_key: str | None = None
|
pixabay_api_key: str | None = None
|
||||||
mods: list[str] = []
|
mods: list[str] = []
|
||||||
|
registration_disabled: bool = False
|
||||||
|
|
||||||
# storage_backend
|
# storage_backend
|
||||||
storage_backend: str | None = "local"
|
storage_backend: str | None = "local"
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ router.include_router(oauth.router, tags=["users", "oauth"], prefix="/oauth")
|
|||||||
response_model_include={"id": ..., "verified": ..., "email": ...},
|
response_model_include={"id": ..., "verified": ..., "email": ...},
|
||||||
)
|
)
|
||||||
async def create_user(user: RouteUser, background_task: BackgroundTasks) -> User | JSONResponse:
|
async def create_user(user: RouteUser, background_task: BackgroundTasks) -> User | JSONResponse:
|
||||||
|
if settings.registration_disabled:
|
||||||
|
raise HTTPException(status_code=423)
|
||||||
user = User(**user.dict(), id=uuid.uuid4(), avatar=gzipped_user_avatar(), created_at=datetime.now())
|
user = User(**user.dict(), id=uuid.uuid4(), avatar=gzipped_user_avatar(), created_at=datetime.now())
|
||||||
try:
|
try:
|
||||||
validate_email(user.email)
|
validate_email(user.email)
|
||||||
|
|||||||
Vendored
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
interface ImportMetaEnv {
|
||||||
|
readonly VITE_APP_TITLE: string;
|
||||||
|
// more env variables...
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ImportMeta {
|
||||||
|
readonly env: ImportMetaEnv;
|
||||||
|
}
|
||||||
+102
-100
@@ -4,7 +4,7 @@ SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
|
|||||||
SPDX-License-Identifier: MPL-2.0
|
SPDX-License-Identifier: MPL-2.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang='ts'>
|
||||||
import '@fontsource/marck-script/index.css';
|
import '@fontsource/marck-script/index.css';
|
||||||
import { getLocalization } from '$lib/i18n';
|
import { getLocalization } from '$lib/i18n';
|
||||||
import { signedIn, pathname } from '$lib/stores';
|
import { signedIn, pathname } from '$lib/stores';
|
||||||
@@ -44,147 +44,149 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav
|
<nav
|
||||||
class="w-screen px-4 lg:px-10 py-2 flex flex-col lg:flex-row lg:items-center fixed backdrop-blur-2xl bg-white/70 shadow-md z-30 top-0"
|
class='w-screen px-4 lg:px-10 py-2 flex flex-col lg:flex-row lg:items-center fixed backdrop-blur-2xl bg-white/70 shadow-md z-30 top-0'
|
||||||
>
|
>
|
||||||
<section class="w-full lg:w-max grid grid-cols-3 lg:grid-cols-2">
|
<section class='w-full lg:w-max grid grid-cols-3 lg:grid-cols-2'>
|
||||||
<a href="/" class="font-black tracking-tight text-xl text-black marck-script link-hover"
|
<a href='/' class='font-black tracking-tight text-xl text-black marck-script link-hover'
|
||||||
>ClassQuiz</a
|
>ClassQuiz</a
|
||||||
>
|
>
|
||||||
<div class="flex justify-center">
|
<div class='flex justify-center'>
|
||||||
<a
|
<a
|
||||||
class="lg:pl-6 text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover"
|
class='lg:pl-6 text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover'
|
||||||
href="/play">{$t('words.play')}</a
|
href='/play'>{$t('words.play')}</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-end">
|
<div class='flex justify-end'>
|
||||||
<button
|
<button
|
||||||
class="lg:hidden dark:text-black"
|
class='lg:hidden dark:text-black'
|
||||||
id="open-menu"
|
id='open-menu'
|
||||||
on:click={toggleMenu}
|
on:click={toggleMenu}
|
||||||
class:hidden={!openMenu}
|
class:hidden={!openMenu}
|
||||||
aria-label="Open navbar"
|
aria-label='Open navbar'
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
width="24"
|
width='24'
|
||||||
height="24"
|
height='24'
|
||||||
viewBox="0 0 24 24"
|
viewBox='0 0 24 24'
|
||||||
fill="none"
|
fill='none'
|
||||||
stroke="currentColor"
|
stroke='currentColor'
|
||||||
stroke-width="2"
|
stroke-width='2'
|
||||||
stroke-linecap="round"
|
stroke-linecap='round'
|
||||||
stroke-linejoin="round"
|
stroke-linejoin='round'
|
||||||
display="block"
|
display='block'
|
||||||
id="TextAlignJustified"
|
id='TextAlignJustified'
|
||||||
>
|
>
|
||||||
<path d="M3 6h18M3 12h18M3 18h18" />
|
<path d='M3 6h18M3 12h18M3 18h18' />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Close menu -->
|
<!-- Close menu -->
|
||||||
<button
|
<button
|
||||||
class="hidden dark:text-black"
|
class='hidden dark:text-black'
|
||||||
id="close-menu"
|
id='close-menu'
|
||||||
class:hidden={openMenu}
|
class:hidden={openMenu}
|
||||||
on:click={toggleMenu}
|
on:click={toggleMenu}
|
||||||
aria-label="Close navbar"
|
aria-label='Close navbar'
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
width="14"
|
width='14'
|
||||||
height="14"
|
height='14'
|
||||||
viewBox="0 0 24 24"
|
viewBox='0 0 24 24'
|
||||||
fill="none"
|
fill='none'
|
||||||
stroke="currentColor"
|
stroke='currentColor'
|
||||||
stroke-width="3"
|
stroke-width='3'
|
||||||
stroke-linecap="round"
|
stroke-linecap='round'
|
||||||
stroke-linejoin="round"
|
stroke-linejoin='round'
|
||||||
display="block"
|
display='block'
|
||||||
id="Cross"
|
id='Cross'
|
||||||
>
|
>
|
||||||
<path d="M20 20L4 4m16 0L4 20" />
|
<path d='M20 20L4 4m16 0L4 20' />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<ul id="menu-items" class="lg:flex w-full flex-col lg:flex-row" class:hidden={openMenu}>
|
<ul id='menu-items' class='lg:flex w-full flex-col lg:flex-row' class:hidden={openMenu}>
|
||||||
<li class="py-2 lg:hidden">
|
<li class='py-2 lg:hidden'>
|
||||||
<BrownButton href="https://mawoka.eu/donate" target="_blank"
|
<BrownButton href='https://mawoka.eu/donate' target='_blank'
|
||||||
>{$t('navbar.donate')} <span class="">❤️</span></BrownButton
|
>{$t('navbar.donate')} <span class=''>❤️</span></BrownButton
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
{#if $signedIn}
|
{#if $signedIn}
|
||||||
<li class="py-2">
|
<li class='py-2'>
|
||||||
<a
|
<a
|
||||||
class="text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover"
|
class='text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover'
|
||||||
href="/dashboard">{$t('words.dashboard')}</a
|
href='/dashboard'>{$t('words.dashboard')}</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="py-2">
|
<li class='py-2'>
|
||||||
<a
|
<a
|
||||||
class="text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover"
|
class='text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover'
|
||||||
href="/explore">{$t('words.explore')}</a
|
href='/explore'>{$t('words.explore')}</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="py-2">
|
<li class='py-2'>
|
||||||
<a
|
<a
|
||||||
class="text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover"
|
class='text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover'
|
||||||
href="/search">{$t('words.search')}</a
|
href='/search'>{$t('words.search')}</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="py-2">
|
<li class='py-2'>
|
||||||
<a
|
<a
|
||||||
class="text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover"
|
class='text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover'
|
||||||
href="/api/v1/users/logout">{$t('words.logout')}</a
|
href='/api/v1/users/logout'>{$t('words.logout')}</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
{:else}
|
{:else}
|
||||||
<li class="py-2">
|
{#if !import.meta.env.VITE_REGISTRATION_DISABLED}
|
||||||
|
<li class='py-2'>
|
||||||
<a
|
<a
|
||||||
class="text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover"
|
class='text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover'
|
||||||
href="/account/register">{$t('words.register')}</a
|
href='/account/register'>{$t('words.register')}</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<li class="py-2">
|
<li class='py-2'>
|
||||||
<a
|
<a
|
||||||
class="text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover"
|
class='text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover'
|
||||||
href="/account/login?returnTo={$pathname}">{$t('words.login')}</a
|
href='/account/login?returnTo={$pathname}'>{$t('words.login')}</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="py-2">
|
<li class='py-2'>
|
||||||
<a
|
<a
|
||||||
class="text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover"
|
class='text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover'
|
||||||
href="/explore">{$t('words.explore')}</a
|
href='/explore'>{$t('words.explore')}</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="py-2">
|
<li class='py-2'>
|
||||||
<a
|
<a
|
||||||
class="text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover"
|
class='text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover'
|
||||||
href="/search">{$t('words.search')}</a
|
href='/search'>{$t('words.search')}</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="py-2">
|
<li class='py-2'>
|
||||||
<a
|
<a
|
||||||
target="_blank"
|
target='_blank'
|
||||||
class="text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover"
|
class='text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover'
|
||||||
href="https://github.com/mawoka-myblock/ClassQuiz">GitHub</a
|
href='https://github.com/mawoka-myblock/ClassQuiz'>GitHub</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="py-2">
|
<li class='py-2'>
|
||||||
<a
|
<a
|
||||||
class="text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover"
|
class='text-lg font-medium lg:px-4 text-gray-600 hover:text-green-600 link-hover'
|
||||||
href="/docs">{$t('words.docs')}</a
|
href='/docs'>{$t('words.docs')}</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
{/if}
|
{/if}
|
||||||
</ul>
|
</ul>
|
||||||
<div
|
<div
|
||||||
class="justify-self-end gap-2 h-full flex justify-center items-center lg:relative fixed right-12 -top-1/2 pt-11 lg:right-0 lg:top-0 lg:p-0"
|
class='justify-self-end gap-2 h-full flex justify-center items-center lg:relative fixed right-12 -top-1/2 pt-11 lg:right-0 lg:top-0 lg:p-0'
|
||||||
>
|
>
|
||||||
<div class="whitespace-nowrap hidden lg:block">
|
<div class='whitespace-nowrap hidden lg:block'>
|
||||||
<BrownButton href="https://mawoka.eu/donate" target="_blank"
|
<BrownButton href='https://mawoka.eu/donate' target='_blank'
|
||||||
>{$t('navbar.donate')} <span class="">❤️</span></BrownButton
|
>{$t('navbar.donate')} <span class=''>❤️</span></BrownButton
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
{#if darkMode}
|
{#if darkMode}
|
||||||
@@ -193,23 +195,23 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
switchDarkMode(false);
|
switchDarkMode(false);
|
||||||
}}
|
}}
|
||||||
use:tippy={{ content: 'Switch light mode on' }}
|
use:tippy={{ content: 'Switch light mode on' }}
|
||||||
aria-label="Activate light mode"
|
aria-label='Activate light mode'
|
||||||
>
|
>
|
||||||
<!-- Heroicons: sun -->
|
<!-- Heroicons: sun -->
|
||||||
<svg
|
<svg
|
||||||
class="w-6 h-6 text-black"
|
class='w-6 h-6 text-black'
|
||||||
fill="none"
|
fill='none'
|
||||||
aria-label="Sun-Icon"
|
aria-label='Sun-Icon'
|
||||||
stroke="currentColor"
|
stroke='currentColor'
|
||||||
viewBox="0 0 24 24"
|
viewBox='0 0 24 24'
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
stroke-linecap="round"
|
stroke-linecap='round'
|
||||||
stroke-linejoin="round"
|
stroke-linejoin='round'
|
||||||
stroke-width="2"
|
stroke-width='2'
|
||||||
stroke="currentColor"
|
stroke='currentColor'
|
||||||
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
|
d='M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z'
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
@@ -218,23 +220,23 @@ SPDX-License-Identifier: MPL-2.0
|
|||||||
on:click={() => {
|
on:click={() => {
|
||||||
switchDarkMode(true);
|
switchDarkMode(true);
|
||||||
}}
|
}}
|
||||||
aria-label="Activate darkmode"
|
aria-label='Activate darkmode'
|
||||||
use:tippy={{ content: 'Switch dark mode on' }}
|
use:tippy={{ content: 'Switch dark mode on' }}
|
||||||
>
|
>
|
||||||
<!-- Heroicons: moon -->
|
<!-- Heroicons: moon -->
|
||||||
<svg
|
<svg
|
||||||
aria-label="Moon-Icon"
|
aria-label='Moon-Icon'
|
||||||
class="w-6 h-6"
|
class='w-6 h-6'
|
||||||
fill="none"
|
fill='none'
|
||||||
stroke="currentColor"
|
stroke='currentColor'
|
||||||
viewBox="0 0 24 24"
|
viewBox='0 0 24 24'
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
stroke-linecap="round"
|
stroke-linecap='round'
|
||||||
stroke-linejoin="round"
|
stroke-linejoin='round'
|
||||||
stroke-width="2"
|
stroke-width='2'
|
||||||
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"
|
d='M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z'
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user