Skip to content

Commit

Permalink
🚧 Maybe fix for overlapping text in old-school mode
Browse files Browse the repository at this point in the history
  • Loading branch information
mawoka-myblock committed Apr 7, 2024
1 parent 5f3f248 commit 33d0ac3
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 84 deletions.
4 changes: 2 additions & 2 deletions frontend/src/lib/editor/sidebar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ SPDX-License-Identifier: MPL-2.0
d="m4.5 15.75 7.5-7.5 7.5 7.5"
stroke-linecap="round"
stroke-linejoin="round"
></path>
/>
</svg>
</div>
<div
Expand Down Expand Up @@ -240,7 +240,7 @@ SPDX-License-Identifier: MPL-2.0
d="m19.5 8.25-7.5 7.5-7.5-7.5"
stroke-linecap="round"
stroke-linejoin="round"
></path>
/>
</svg>
</div>
</div>
Expand Down
52 changes: 27 additions & 25 deletions frontend/src/lib/play/question.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -234,33 +234,35 @@ SPDX-License-Identifier: MPL-2.0
</div>
{/await}
{:else if question.type === QuizQuestionType.TEXT}
<span
class="fixed top-0 bg-red-500 h-8 transition-all"
style="width: {(100 / parseInt(question.time)) * parseInt(timer_res)}vw"
/>
<div class="flex justify-center mt-10">
<p class="text-black dark:text-white">Enter your answer</p>
</div>
<div class="flex justify-center m-2">
<input
type="text"
bind:value={text_input}
disabled={selected_answer}
class="bg-gray-50 focus:ring text-gray-900 rounded-lg focus:ring-blue-500 block w-full p-2 dark:bg-gray-700 dark:text-white dark:focus:ring-blue-500 outline-none transition text-center disabled:opacity-50 disabled:cursor-not-allowed"
<div>
<span
class="fixed top-0 bg-red-500 h-8 transition-all"
style="width: {(100 / parseInt(question.time)) * parseInt(timer_res)}vw"
/>
</div>

<div class="flex justify-center mt-2">
<div class="w-1/3">
<BrownButton
type="button"
<div class="flex justify-center mt-10">
<p class="text-black dark:text-white">Enter your answer</p>
</div>
<div class="flex justify-center m-2">
<input
type="text"
bind:value={text_input}
disabled={selected_answer}
on:click={() => {
selectAnswer(text_input);
}}
>
{$t('words.submit')}
</BrownButton>
class="bg-gray-50 focus:ring text-gray-900 rounded-lg focus:ring-blue-500 block w-full p-2 dark:bg-gray-700 dark:text-white dark:focus:ring-blue-500 outline-none transition text-center disabled:opacity-50 disabled:cursor-not-allowed"
/>
</div>

<div class="flex justify-center mt-2">
<div class="w-1/3">
<BrownButton
type="button"
disabled={selected_answer}
on:click={() => {
selectAnswer(text_input);
}}
>
{$t('words.submit')}
</BrownButton>
</div>
</div>
</div>
{:else if question.type === QuizQuestionType.RANGE}
Expand Down
78 changes: 59 additions & 19 deletions frontend/src/routes/account/settings/security/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ SPDX-License-Identifier: MPL-2.0
if (!browser || user_data?.require_password === undefined) {
return;
}
const pw = require_password()
const pw = require_password();
const res = await fetch('/api/v1/users/2fa/require_password', {
method: 'POST',
headers: {
Expand All @@ -48,13 +48,20 @@ SPDX-License-Identifier: MPL-2.0
};
const require_password = (): string => {
return prompt("Please enter your password to continue")
}
return prompt('Please enter your password to continue');
};
const add_security_key = async () => {
const pw = require_password()
const res1 = await fetch('/api/v1/users/webauthn/add_key_init', {method: "POST", body: JSON.stringify({password: pw}), headers: { 'Content-Type': 'application/json' }});
if (res1.status === 401) {alert("Password probably wrong"); return}
const pw = require_password();
const res1 = await fetch('/api/v1/users/webauthn/add_key_init', {
method: 'POST',
body: JSON.stringify({ password: pw }),
headers: { 'Content-Type': 'application/json' }
});
if (res1.status === 401) {
alert('Password probably wrong');
return;
}
if (!res1.ok) {
throw Error('Response not ok');
}
Expand All @@ -81,34 +88,62 @@ SPDX-License-Identifier: MPL-2.0
};
const remove_security_key = async (key_id: number) => {
const pw = require_password()
const res = await fetch(`/api/v1/users/webauthn/key/${key_id}`, { method: 'DELETE', body: JSON.stringify({password: pw}), headers: { 'Content-Type': 'application/json' } });
if (res.status === 401) {alert("Password probably wrong"); return}
const pw = require_password();
const res = await fetch(`/api/v1/users/webauthn/key/${key_id}`, {
method: 'DELETE',
body: JSON.stringify({ password: pw }),
headers: { 'Content-Type': 'application/json' }
});
if (res.status === 401) {
alert('Password probably wrong');
return;
}
data = get_data();
};
const disable_totp = async () => {
const pw = require_password()
const res = await fetch(`/api/v1/users/2fa/totp`, { method: 'DELETE', body: JSON.stringify({password: pw}), headers: { 'Content-Type': 'application/json' } });
if (res.status === 401) {alert("Password probably wrong"); return}
const pw = require_password();
const res = await fetch(`/api/v1/users/2fa/totp`, {
method: 'DELETE',
body: JSON.stringify({ password: pw }),
headers: { 'Content-Type': 'application/json' }
});
if (res.status === 401) {
alert('Password probably wrong');
return;
}
data = get_data();
};
const enable_totp = async () => {
const pw = require_password()
const res = await fetch('/api/v1/users/2fa/totp', { method: 'POST', body: JSON.stringify({password: pw}), headers: { 'Content-Type': 'application/json' } });
if (res.status === 401) {alert("Password probably wrong"); return}
const pw = require_password();
const res = await fetch('/api/v1/users/2fa/totp', {
method: 'POST',
body: JSON.stringify({ password: pw }),
headers: { 'Content-Type': 'application/json' }
});
if (res.status === 401) {
alert('Password probably wrong');
return;
}
data = get_data();
totp_data = await res.json();
};
const get_backup_code = async () => {
const pw = require_password()
const pw = require_password();
if (!confirm('If you continue, your old backup-code will be removed.')) {
return;
}
const res = await fetch('/api/v1/users/2fa/backup_code', { method: 'POST', body: JSON.stringify({password: pw}), headers: { 'Content-Type': 'application/json' } });
if (res.status === 401) {alert("Password probably wrong"); return}
const res = await fetch('/api/v1/users/2fa/backup_code', {
method: 'POST',
body: JSON.stringify({ password: pw }),
headers: { 'Content-Type': 'application/json' }
});
if (res.status === 401) {
alert('Password probably wrong');
return;
}
backup_code = (await res.json()).code;
};
</script>
Expand All @@ -130,7 +165,12 @@ SPDX-License-Identifier: MPL-2.0
</div>
<div class="h-full w-full">
<h2 class="text-center text-2xl">{$t('security_settings.activate_2fa')}</h2>
<div class="flex h-full w-full justify-center flex-col" class:pointer-events-none={!totp_activated} class:grayscale={!totp_activated} class:opacity-50={!totp_activated}>
<div
class="flex h-full w-full justify-center flex-col"
class:pointer-events-none={!totp_activated}
class:grayscale={!totp_activated}
class:opacity-50={!totp_activated}
>
<div class="m-auto">
{#if user_data.require_password}
<div class="flex items-center space-x-2">
Expand Down
80 changes: 42 additions & 38 deletions frontend/src/routes/docs/self-host/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
SPDX-License-Identifier: MPL-2.0
-->
<script lang='ts'>
<script lang="ts">
import { onMount } from 'svelte';
import '$lib/hljs.css';
Expand All @@ -16,12 +16,12 @@ SPDX-License-Identifier: MPL-2.0
<svelte:head>
<title>ClassQuiz/docs - Self-Host</title>
<meta
name='description'
content='How to self-host ClassQuiz, the open-source quiz-application'
name="description"
content="How to self-host ClassQuiz, the open-source quiz-application"
/>
</svelte:head>
<article
class='prose prose-sm sm:prose lg:prose-lg xl:prose-xl mx-auto mt-10 prose-slate px-4 dark:prose-invert'
class="prose prose-sm sm:prose lg:prose-lg xl:prose-xl mx-auto mt-10 prose-slate px-4 dark:prose-invert"
>
<h1>Self-Hosting</h1>
<p>Since ClassQuiz is open-source, it can also be self-hosted.</p>
Expand All @@ -36,40 +36,42 @@ SPDX-License-Identifier: MPL-2.0
<h3>Software</h3>
<ul>
<li>
<a href='https://docker.com' target='_blank'>Docker</a> (<a
href='https://docs.docker.com/compose/install/linux/'
target='_blank'>Compose</a
>)
<a href="https://docker.com" target="_blank">Docker</a> (<a
href="https://docs.docker.com/compose/install/linux/"
target="_blank">Compose</a
>)
</li>
<li><a href='https://git-scm.com/' target='_blank'>Git</a></li>
<li><a href="https://git-scm.com/" target="_blank">Git</a></li>
<li>
A <a href='https://redis.com' target='_blank'>Redis</a>-Server
A <a href="https://redis.com" target="_blank">Redis</a>-Server
</li>
</ul>
<h3>3rd-Parties</h3>
<h4>Optional</h4>
<ul>
<li><a href='https://sentry.io'>Sentry (Error-Logging)</a></li>
<li><a href="https://sentry.io">Sentry (Error-Logging)</a></li>
<li>
<a href='https://console.cloud.google.com/apis/dashboard'
>Google-Credentials (Sign-In)</a
<a href="https://console.cloud.google.com/apis/dashboard"
>Google-Credentials (Sign-In)</a
>
</li>
<li><a href='https://github.com/settings/developers'>GitHub-Credentials (Sign-In)</a></li>
<li><a href='https://hcaptcha.com'>hCaptcha</a> <b>OR</b> <a href='https://www.google.com/recaptcha/about/'>ReCaptcha</a></li>

<li><a href="https://github.com/settings/developers">GitHub-Credentials (Sign-In)</a></li>
<li>
<a href="https://hcaptcha.com">hCaptcha</a> <b>OR</b>
<a href="https://www.google.com/recaptcha/about/">ReCaptcha</a>
</li>
</ul>

<h2>Installation</h2>
<p>At first, clone the repo:</p>

<pre><code class='language-bash'
>git clone https://github.com/mawoka-myblock/classquiz && cd ClassQuiz</code
></pre>
<pre><code class="language-bash"
>git clone https://github.com/mawoka-myblock/classquiz && cd ClassQuiz</code
></pre>
<p>
Now, you'll configure your frontend. You'll have to change the following in <code
>frontend/Dockerfile</code
>:
>frontend/Dockerfile</code
>:
</p>
<ul>
<li><code>VITE_MAPBOX_ACCESS_TOKEN</code>: A Mapbox-token which is optional.</li>
Expand All @@ -93,7 +95,7 @@ SPDX-License-Identifier: MPL-2.0
<h3>Storage Provider</h3>
<p>
You'll have to set up a storage provider for some pictures (these getting imported from
Kahoot!). For now, you can use <a href='https://min.io/' target='_blank'>Minio (S3)</a> or
Kahoot!). For now, you can use <a href="https://min.io/" target="_blank">Minio (S3)</a> or
the local filesystem. Please not that I'd recommend Minio for larger instances, since it can
be scaled and the media doesn't have to streamed through the (comparatively) slow ClassQuiz
server. Now, that you've decided on a storage backend, you can set the
Expand Down Expand Up @@ -124,9 +126,9 @@ SPDX-License-Identifier: MPL-2.0
</p>
<h4>Google</h4>
<p>
First, go to <a href='https://console.cloud.google.com/apis/dashboard'
>console.cloud.google.com/apis/dashboard</a
> and create a new project and select it. Then, go to the "OAuth consent screen" and set it up.
First, go to <a href="https://console.cloud.google.com/apis/dashboard"
>console.cloud.google.com/apis/dashboard</a
> and create a new project and select it. Then, go to the "OAuth consent screen" and set it up.
Next, go to the "Credentials"-tab and click on "Create Credentials" and create a new "OAuth Client
ID". This ID should be from the application-type "Web application". Afterwards, add a new "Authorised
JavaScript origin", which is just the base-domain (with https) of your ClassQuiz-installation.
Expand All @@ -137,31 +139,33 @@ SPDX-License-Identifier: MPL-2.0

<h4>GitHub</h4>
<p>
First, go to <a href='https://github.com/settings/developers'
>github.com/settings/developers</a
> and create a "new OAuth App". The "Authorization callback URL" has the following schema:
First, go to <a href="https://github.com/settings/developers"
>github.com/settings/developers</a
> and create a "new OAuth App". The "Authorization callback URL" has the following schema:
</p>
<pre><code>https://[BASE_URL]/api/v1/users/oauth/github/auth</code></pre>
<p>
That's it. Click on "Register application" and generate a new client secret and save it for
later, together with your client-id.
</p>
<h4>Custom OpenID auth</h4>
<p>A login using a custom OpenID provider is also possible. For that, adjust the settings in the docker-compose.yml
and configure the following scopes: "openid email profile". The follwoing redirect-url should be used:</p>
<p>
A login using a custom OpenID provider is also possible. For that, adjust the settings in
the docker-compose.yml and configure the following scopes: "openid email profile". The
follwoing redirect-url should be used:
</p>
<pre><code>https://[BASE_URL]/api/v1/users/oauth/custom/auth</code></pre>
You'll also need to tell the frontend by editing the <code>frontend/Dockerfile</code>. Add the following line at the
top, where all the other ENV's are as well:
You'll also need to tell the frontend by editing the<code>frontend/Dockerfile</code>. Add the
following line at the top, where all the other ENV's are as well:
<pre><code>ENV VITE_CUSTOM_OAUTH_NAME=[SOME_DISPLAY_NAME_FOR_THE_PROVIDER]</code></pre>


<h3>Docker-Compose File</h3>
Please go through the <code>docker-compose.yml</code> thoroughly and fill out all the details, which should be
self-explanatory.
Please go through the<code>docker-compose.yml</code> thoroughly and fill out all the details,
which should be self-explanatory.
<p>Run the following command to generate and set the secret up automatically</p>
<pre><code class='language-bash'
>sed -i "s/TOP_SECRET/$(openssl rand -hex 32)/g" docker-compose.yml</code
></pre>
<pre><code class="language-bash"
>sed -i "s/TOP_SECRET/$(openssl rand -hex 32)/g" docker-compose.yml</code
></pre>
<p>Now build and deploy:</p>
<pre><code>docker compose build && docker compose up -d</code></pre>
<p><b>ClassQuiz needs HTTPS/SSL to work properly!</b></p>
Expand Down

0 comments on commit 33d0ac3

Please sign in to comment.