Self registration #60

Merged
dergrimm merged 1 commit from self-registration into main 2022-02-15 20:06:54 +00:00
5 changed files with 173 additions and 12 deletions

View file

@ -21,9 +21,6 @@ module Backend
module Api
# GraphQL request context class
class Context < GraphQL::Context
# Request object
getter request
# Development mode
getter development : Bool
@ -39,10 +36,10 @@ module Backend
# User's external object
getter external : (Db::Teacher | Db::Student)?
def initialize(@request : HTTP::Request, @development : Bool, *rest)
def initialize(request : HTTP::Request, @development : Bool, *rest)
super(*rest)
token = @request.headers["Authorization"]?
token = request.headers["Authorization"]?
if token && token[..Auth::BEARER.size - 1] == Auth::BEARER
payload = Auth.decode_jwt?(token[Auth::BEARER.size..])
return unless payload

View file

@ -127,6 +127,16 @@ module Backend
id
end
@[GraphQL::Field]
# Self register as student
def register_student(context : Context, input : StudentInput) : Student
context.student! external_check: false
Student.new(
Db::Student.create!(user_id: context.user.not_nil!.id, skif: input.skif)
)
end
@[GraphQL::Field]
# Creates vote for authenticated user's student
def create_vote(context : Context, input : VoteCreateInput) : Vote

View file

@ -1,7 +1,10 @@
<script lang="ts">
import { initClient } from "@urql/svelte";
import { removeCookie } from "typescript-cookie";
import { session } from "$app/stores";
import { goto } from "$app/navigation";
import * as cookieNames from "$lib/cookieNames";
initClient({
url: "/graphql",
@ -17,8 +20,28 @@
return {};
},
});
function logout(): void {
$session.user.token = undefined;
removeCookie(cookieNames.TOKEN);
goto("/login");
}
</script>
<nav>
<ul>
<li>
{#if $session.user.token}
<button on:click={logout}>Logout</button>
{:else}
<button><a href="/login">Login</a></button>
{/if}
</li>
</ul>
</nav>
<hr />
<main>
<slot />
</main>

View file

@ -16,9 +16,11 @@
</script>
<script lang="ts">
import { operationStore, query, gql } from "@urql/svelte";
import { operationStore, query, gql, mutation } from "@urql/svelte";
import * as svelteForms from "svelte-forms";
import * as validators from "svelte-forms/validators";
import type { User } from "$lib/graphql";
import type { User, Teacher, Student } from "$lib/graphql";
import { UserRole } from "$lib/graphql";
interface Data {
@ -44,6 +46,82 @@
}
`);
query(meStore);
const teacherRegisterFormMaxStudents = svelteForms.field("maxStudents", 0, [
validators.required(),
validators.min(0),
]);
const teacherRegisterFormSkif = svelteForms.field("skif", false);
const teacheRegisterForm = svelteForms.form(
teacherRegisterFormMaxStudents,
teacherRegisterFormSkif
);
interface RegisterTeacherData {
registerTeacher: Teacher;
}
interface RegisterTeacherVars {
maxStudents: number;
skif: boolean;
}
const registerTeacherStore = operationStore<
RegisterTeacherData,
RegisterTeacherVars
>(gql`
mutation RegisterTeacher($maxStudents: Int!, $skif: Boolean!) {
registerTeacher(input: { maxStudents: $maxStudents, skif: $skif }) {
id
}
}
`);
const registerTeacherMutation = mutation(registerTeacherStore);
async function registerTeacher(): Promise<void> {
await registerTeacherMutation({
maxStudents: $teacherRegisterFormMaxStudents.value,
skif: $teacherRegisterFormSkif.value,
});
if (!$registerTeacherStore.error && $registerTeacherStore.data) {
location.reload();
}
}
const registerStudentSkif = svelteForms.field("skif", false);
const registerStudentForm = svelteForms.form(registerStudentSkif);
interface RegisterStudentData {
registerStudent: Student;
}
interface RegisterStudentVars {
skif: boolean;
}
const registerStudentStore = operationStore<
RegisterStudentData,
RegisterStudentVars
>(gql`
mutation RegisterStudent($skif: Boolean!) {
registerStudent(input: { skif: $skif }) {
id
}
}
`);
const registerStudentMutation = mutation(registerStudentStore);
async function registerStudent(): Promise<void> {
await registerStudentMutation({
skif: $registerStudentSkif.value,
});
if (!$registerStudentStore.error && $registerStudentStore.data) {
location.reload();
}
}
</script>
{#if $meStore.error}
@ -56,11 +134,64 @@
{#if $meStore.data.me.role === UserRole.TEACHER}
{#if !$meStore.data.me.teacher}
<p>Registriere dich jetzt als Lehrer!</p>
<p>Registriere dich jetzt als Lehrer:</p>
<form on:submit|preventDefault={registerTeacher}>
<label for="maxStudents">Maximale Schüler:</label>
<br />
<input
type="number"
name="maxStudents"
min="0"
bind:value={$teacherRegisterFormMaxStudents.value}
/>
<br />
<label for="skif">SKIF:</label>
<br />
<input
type="checkbox"
name="skif"
bind:checked={$teacherRegisterFormSkif.value}
/>
<br /><br />
<button type="submit" disabled={!$teacheRegisterForm.valid}
>Registrieren</button
>
</form>
{#if $registerTeacherStore.error}
<p style="color: red;">{$registerTeacherStore.error.message}</p>
{:else if $registerTeacherStore.fetching}
<p>Laden...</p>
{:else if $registerTeacherStore.data}
<p>Registrierung erfolgreich!</p>
{/if}
{/if}
{:else if $meStore.data.me.role === UserRole.STUDENT}
{#if !$meStore.data.me.student}
<p>Registriere dich jetzt als Schüler!</p>
<p>Registriere dich jetzt als Schüler:</p>
<form on:submit|preventDefault={registerStudent}>
<label for="skif">SKIF:</label>
<br />
<input
type="checkbox"
name="skif"
bind:checked={$registerStudentSkif.value}
/>
<br /><br />
<button type="submit" disabled={!$registerStudentForm.valid}
>Registrieren</button
>
</form>
{#if $registerStudentStore.error}
<p style="color: red;">{$registerStudentStore.error.message}</p>
{:else if $registerStudentStore.fetching}
<p>Laden...</p>
{:else if $registerStudentStore.data}
<p>Registrierung erfolgreich!</p>
{/if}
{/if}
{/if}
{/if}

View file

@ -35,7 +35,7 @@
`);
const login = mutation(loginStore);
async function submit(event: Event): Promise<void> {
async function submit(): Promise<void> {
await login({
username: $username.value as string,
password: $password.value as string,
@ -58,13 +58,13 @@
<br />
<input type="text" id="username" bind:value={$username.value} />
<br />
<label for="password">Password</label>
<label for="password">Kennwort:</label>
<br />
<input type="password" id="password" bind:value={$password.value} />
<br /><br />
<button type="submit" disabled={!$loginForm.valid}> Login </button>
<button type="submit" disabled={!$loginForm.valid}>Login</button>
<br />